在 iOS 应用程序小部件中,我只能在某些设备上看到双倍数据(见下图)。我试图识别设备、iOS 版本,但它似乎是“随机的”。另外,我无法自己调试它,因为在我的每台设备上,所有内容都正确呈现并且进行盲调试不起作用(AppStore 上的几次更新但仍然出现相同的错误)。
在小部件中,我(在后台线程中)从网络下载新数据并将它们(在 dispatch_get_main_queue()
中)放入标签、图像等中。一切正常,但有时旧数据未清除”。在我的小部件设计文件中,我已经清除了所有“默认”文本,所以这不是这个问题。
双图标和文本 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;
}
}
最佳答案
查看生命周期
不要重复
/li>viewDidLoad
和viewWillAppear/viewDidAppear
中的工作。
加载的 View 将命中所有三个 方法。将viewDidLoad
用于在UIViewController
的生命周期内必须恰好执行一次的操作。
潜在问题:
触发对[self updateData]
的 3 次调用,可能相互冲突,可能与竞争的NCUpdateResult
完成处理程序3。平衡观察者
看来
addObserver
从未被removeObserver
平衡。这些注册方法的一个很好的位置是一组平衡的消息,例如view___Appear
和view___Disappear
方法,如 StackOverflow answer 中所述。 .
潜在问题:
持久注册可能超出范围的对象的通知。不缓存操作系统处理程序
可能滥用
NCUpdateResultNewData
完成处理程序:NCUpdateResult
被传递给widgetPerformUpdateWithCompletionHandler
以用于该特定调用,而不是存储以供多次重用.它可能应该作为参数传递给updateData
而不是存储在全局中,然后传递给FillData
,并最终在一次性使用。if (nil != self.completionHandler) { self.completionHandler(NCUpdateResultNewData); self.completionHandler = nil; // One time use }
对
widgetPerformUpdateWithCompletionHandler
的每次调用都有自己的周期,如 this StackOverflow answer 中所述。 .布局和自动布局
请注意,iOS 正在制作您的小部件的快照;在 Interface Builder 中,确保使用正确的 View 分层。特别注意透明度和绘图标志。利用自动布局调整对象大小/调整大小/对齐对象
关于iOS - Objective-C - 小部件文本和图像加倍 - 旧数据未清除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40471989/