在iOS app小部件中,我只能看到一些设备,数据翻倍(见下图)。我试图识别设备,iOS版本,但它似乎是“随机的”。另外,我无法自行调试,因为在我的每个设备上,所有设备都正确呈现并且无法进行盲调试(AppStore上的多次更新但仍然存在相同的错误)。
在小部件中,我从Web下载(在后台线程中)新数据并将它们(在dispatch_get_main_queue()
中)放入标签,图像等中。一切正常,但有时旧数据不会被“清除”。在我的小部件设计文件中,我已经清除了所有“默认”文本,所以这不是这个问题。
Doubled icon&文本4.1°C和7.9°C重叠
我的小部件代码的主要部分是(通过删除其他标签,表格和地理位置缩短):
- (void)viewDidLoad
{
[super viewDidLoad];
if ([self.extensionContext respondsToSelector:@selector(widgetLargestAvailableDisplayMode)])
{
//this is iOS >= 10
self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(FinishDownload:) name:@"FinishDownload" object:nil];
self.preferredContentSize = CGSizeMake(320, 160);
[self updateData];
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self updateData];
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self updateData];
}
-(void)updateData
{
[[[DataManager SharedManager] settings] Reload];
[[CoreDataManager SharedManager] reset];
if ([[DataManager SharedManager] DownloadDataWithAfterSelector:@"FinishDownload"] == NO)
{
//no need to download update - refill data now
//if downloading - wait for download
[self FillData];
}
}
}
-(void)FinishDownload:(NSNotification *)notification
{
dispatch_async(dispatch_get_main_queue(), ^{
[self FillData];
});
}
-(void)FillData
{
//a lot of code - example of setting temperature
NSString *str = [NSString stringWithFormat:@"%@ °C", act.temp_act];
self.lblTemp.text = str;
[self.lblTemp sizeToFit];
if (self.completionHandler != nil)
{
self.completionHandler(NCUpdateResultNewData);
}
}
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler
{
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResultFailed
// If there's no update required, use NCUpdateResultNoData
// If there's an update, use NCUpdateResultNewData
//completionHandler(NCUpdateResultNewData);
NSLog(@"=== widgetPerformUpdateWithCompletionHandler === ");
self.completionHandler = completionHandler;
[self updateData];
}
- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets
{
return UIEdgeInsetsMake(0, 0, 5, 5);
}
- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize
{
if (activeDisplayMode == NCWidgetDisplayModeExpanded)
{
self.preferredContentSize = CGSizeMake(320, 160);
}
else if (activeDisplayMode == NCWidgetDisplayModeCompact)
{
self.preferredContentSize = maxSize;
}
}
答案 0 :(得分:1)
请勿在{{1}}和viewDidLoad
中复制作品
已加载的视图将点击所有三种方法。使用viewWillAppear/viewDidAppear
进行必须在viewDidLoad
的生命周期内执行一次的操作
潜在问题:
可能会与竞争UIViewController
完成处理程序 3 触发3次可能相互冲突的调用(可能是冲突的){/ p>
似乎[self updateData]
永远不会被NCUpdateResult
平衡。这些注册方法的一个好位置是一组平衡消息,例如addObserver
和removeObserver
方法,如StackOverflow answer中所述。
潜在问题:
持久注册可能超出范围的对象的通知。
可能滥用view___Appear
完成处理程序:view___Disappear
传递给NCUpdateResultNewData
以用于该特定调用,而不是存储以供多次重用。它可能应该作为参数传递给NCUpdateResult
而不是存储在全局中,然后传递给widgetPerformUpdateWithCompletionHandler
,并在一次性使用后最终清除。 / p>
updateData
FillData
的每个调用都有自己的周期,如this StackOverflow answer中所述。
请注意iOS正在制作小部件的快照;在Interface Builder中,确保使用适当的视图分层。特别注意透明度和绘制标志。利用Autolayout调整大小/大小/捕捉对象
答案 1 :(得分:1)
检查Interface Builder中的UILabel选项,确保' opaque'未经检查。如果标签设置为不透明,则在更改文本时可能无法正确清除整个视图。您可能想要检查“清除图形上下文”'属性也应该检查。
答案 2 :(得分:1)
在代码中添加通知观察器。你没有删除观察者。
我怀疑通知会被多次触发,这将导致jn出现竞争状况。
解决方案: - 检查hoe经常执行addObserver。 (包括屏幕更改,如后退等)
在捕获通知时删除观察者。
离开VC时清除/删除观察者
此外:检查/减少ViewWillAppear和ViwDidAppear中的操作。