UINavigationController method setToolbarHidden bug in Xcode 9: infinite calculation of auto-layout constraints leads to OOM

丶灬走出姿态 提交于 2019-12-04 06:41:28

This is the answer from a developer from the same team as OP is from.

After one more round of research we have found that the problem was on our side:

- (NSArray *)toolbarItems
{
  return [self toolbarItemsWithRunningAdditionalAnimation:NO];
}

Original developer made the method toolbarItemsWithRunningAdditionalAnimation to return new objects each time the method was called. When going to this controller iOS calls toolbarItems at least 3 times so giving it new objects every time we made iOS confused so it was recalculating auto-layout constraints in an infinite loop. Our original fix below is also working, however it becomes obsolete as we start always returning the same array of items like:

- (NSArray *)toolbarItems {
  if (_cachedToolbarItems) { return _cachedToolbarItems; }

  _cachedToolbarItems = [self toolbarItemsWithRunningAdditionalAnimation:NO];

  return _cachedToolbarItems'
}

We are doing the following in our app (pseudocode):

UIToolbar *toolbar = self.navigationController.toolbar;

NSArray <UIBarButtonItem *> *items = @[
  flexibleSpace, 
  share, 
  flexibleSpace, 
  play, 
  flexibleSpace, 
  stats, 
  flexibleSpace
];
[toolbar setItems:items animated:animated];

[self.navigationController setToolbarHidden:NO animated:animated];

The problematic items that caused infinite calculation of auto-layout constraints were share and stats. The thing they both had in common - they both were created using -[UIBarButtonItem initWithImage:style:target:action:] initializer. When we started using another initializer:

 UIButton *customShareButton = ... // we create button ourselves.
 UIBarButtonItem *shareItem = [[UIBarButtonItem alloc] initWithCustomView: customShareButton];

The problem went away.

Besides the accepted answer, we found that our problem was related to the fact that in our class, we override the method - (NSArray *)toolbarItems.

Every time our method is called, a new set of toolbarItems is created. Seems like from iOS 11, every time new toolbar items are returned to this method, UINavigationController:layoutIfNeeded is called again, which in turn calls toolbarItems which returns new items because of our implementation. This causes an infinite loop.

If you encounter this problem, check if you are overriding - (NSArray *)toolbarItems

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!