【问题标题】:How to prepare UI update before app enter foreground如何在应用程序进入前台之前准备 UI 更新
【发布时间】:2016-03-22 01:56:29
【问题描述】:

我知道当 Apple 不推荐后台应用程序时更新 UI,尤其是对于 OpenGL。

但是,我刚刚意识到 iMessenger 和 Facebook 的 Messenger 看起来可以做到这一点。和你的朋友输入一个消息线程然后去后台,然后在应用还在后台的时候收到一条新消息,然后把这个应用带到前台(点击推送通知或应用图标),你会发现新消息气泡是已经有来自图标的应用扩展动画。

据我了解,这只会发生,因为新消息气泡已经在后台模式下绘制。然后当应用进入前台时,它可以出现在动画中。

但是从我的测试结果来看,在 iOS8 和 iOS9 中,所有的后台 UI 更新都会在应用激活后推迟。此外,iOS 将为该 UI 更新添加一个隐式动画事务。

我在下面列出了我的测试代码,当应用程序进入前台时,您会看到新单元格被添加到表格中,并带有明显的动画事务,这与 iMessenger 完全不同。 tableView:numberOfRowsInSection: 只会在应用进入前台时延迟执行。

而且不只是tableview单元格更新,即使在后台添加子视图也会触发类似的延迟事务进入前台。

也许我在这方面的方向完全错误。谁能帮助我了解 iMessenger 和 FB 的 Messenger 是如何实现这种效果的? 提前致谢!

@interface ViewController () <UITableViewDataSource, UITableViewDelegate>

@property (nonatomic) UITableView *tableView;
@property (nonatomic) NSMutableArray *dataTable;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
  [self.view addSubview:self.tableView];
  self.tableView.delegate = self;
  self.tableView.dataSource = self;
  [self.tableView registerClass:[UITableViewCell class]
         forCellReuseIdentifier:@"kCellId"];

  self.dataTable = [[NSMutableArray alloc] initWithArray:@[@"1", @"2", @"3"]];

  __weak __typeof(self) weakSelf = self;
  [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification
                                                    object:nil
                                                     queue:[NSOperationQueue mainQueue]
                                                usingBlock:^(NSNotification * _Nonnull note) {
                                                  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)),
                                                                 dispatch_get_main_queue(), ^{
                                                    [weakSelf.dataTable addObject:[@(weakSelf.dataTable.count + 1) stringValue]];
                                                    [weakSelf.tableView reloadData];
                                                  });
                                                }];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  return self.dataTable.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"kCellId"];
  cell.textLabel.text = self.dataTable[indexPath.row];
  return cell;
}

@end

【问题讨论】:

  • 你为什么使用dispatch_after?这迫使等待一个运行循环并稍后执行该块 - 在屏幕已经绘制一次之后。 NSNotificationCenter 实际上总是 在主线程中调用它的观察者。这意味着您根本不必使用 GCD。尝试删除dispatch_after 调用。
  • 使用 dispatch_after 是在后台尝试模拟更新 UI。确实进入后台通知后直接调用 UI update 不能保证核心动画已经停止。
  • 我建议不要对这样的测试用例进行硬编码。如果您想要更好的测试,我会向您的应用发送推送通知,其中包含一些任意数据。当应用收到推送通知时,使用从推送通知收到的数据更新 dataTable。

标签: ios user-interface animation


【解决方案1】:

我可以建议您查看 APN payload documentation 以了解 launch-mage

launch-image - 应用程序包中图像文件的文件名;它可以包括扩展名或省略它。当用户点击操作按钮或移动操作滑块时,该图像用作启动图像。如果未指定此属性,则系统要么使用先前的快照,要么使用应用程序 Info.plist 文件中由 UILaunchImageFile 键标识的图像,或者回退到 Default.png。 此属性是在 iOS 4.0 中添加的。

【讨论】:

    【解决方案2】:

    Background Fetch 允许系统在后台唤醒应用程序

    更多细节 enter link description here

    【讨论】:

    • 感谢您的回复,但是即使应用程序在后台唤醒,所有 UI 更新都将发布到激活状态。至少适用于 8.0 之后的 iOS 版本
    猜你喜欢
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多