iOS - Objective-C - 小部件文本和图像加倍 - 旧数据不会被清除

时间:2016-11-07 18:25:27

标签: ios widget

在iOS app小部件中,我只能看到一些设备,数据翻倍(见下图)。我试图识别设备,iOS版本,但它似乎是“随机的”。另外,我无法自行调试,因为在我的每个设备上,所有设备都正确呈现并且无法进行盲调试(AppStore上的多次更新但仍然存在相同的错误)。

在小部件中,我从Web下载(在后台线程中)新数据并将它们(在dispatch_get_main_queue()中)放入标签,图像等中。一切正常,但有时旧数据不会被“清除”。在我的小部件设计文件中,我已经清除了所有“默认”文本,所以这不是这个问题。

enter image description here

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;            
    }
}

3 个答案:

答案 0 :(得分:1)

  1. 查看生命周期

    请勿在{{1​​}}和viewDidLoad中复制作品 已加载的视图将点击所有三种方法。使用viewWillAppear/viewDidAppear进行必须在viewDidLoad的生命周期内执行一次的操作 潜在问题
    可能会与竞争UIViewController完成处理程序 3 触发3次可能相互冲突的调用(可能是冲突的){/ p>

  2. 余额观察员

    似乎[self updateData]永远不会被NCUpdateResult平衡。这些注册方法的一个好位置是一组平衡消息,例如addObserverremoveObserver方法,如StackOverflow answer中所述。 潜在问题
    持久注册可能超出范围的对象的通知。

  3. 不缓存OS处理程序

    可能滥用view___Appear完成处理程序:view___Disappear传递给NCUpdateResultNewData以用于该特定调用,而不是存储以供多次重用。它可能应该作为参数传递给NCUpdateResult而不是存储在全局中,然后传递给widgetPerformUpdateWithCompletionHandler,并在一次性使用后最终清除。 / p>

    updateData

    FillData的每个调用都有自己的周期,如this StackOverflow answer中所述。

  4. 布局&自动布局

    请注意iOS正在制作小部件的快照;在Interface Builder中,确保使用适当的视图分层。特别注意透明度和绘制标志。利用Autolayout调整大小/大小/捕捉对象

答案 1 :(得分:1)

检查Interface Builder中的UILabel选项,确保' opaque'未经检查。如果标签设置为不透明,则在更改文本时可能无法正确清除整个视图。您可能想要检查“清除图形上下文”'属性也应该检查。

答案 2 :(得分:1)

在代码中添加通知观察器。你没有删除观察者。

我怀疑通知会被多次触发,这将导致jn出现竞争状况。

解决方案: - 检查hoe经常执行addObserver。 (包括屏幕更改,如后退等)

  • 在捕获通知时删除观察者。

  • 离开VC时清除/删除观察者

此外:检查/减少ViewWillAppear和ViwDidAppear中的操作。