添加到滚动视图后,完全加载的 UIViewController 丢失所有数据

发布于 2024-08-31 08:11:30 字数 1905 浏览 8 评论 0原文

摘要

我正在重新利用 Apple 的页面控制项目。在 loadScrollViewWithPage: 中,我添加到滚动视图的视图控制器出现在屏幕上,但没有初始化值,就像直接从笔尖显示一样。

具体

这是当我单步执行时似乎正在工作的代码:

 CBFullScreenViewController *controller = [viewControllers objectAtIndex:page];

 if ((NSNull *)controller == [NSNull null]) {
  controller = [[CBFullScreenViewController alloc] init];

  // Populate the view from the corresponding CBImage object
  CBImage *imageObject = [imageArray objectAtIndex:page];
  BOOL bookmarked = [imageObject.bookmarked boolValue];
  controller.bookmarkButton.highlighted = bookmarked;
  NSString *subtitle = imageObject.subtitle;
  controller.closedSubtitleLabel.text = subtitle;
     // <-- snip...more initialization --> //
  controller.delegate = self;

  [viewControllers replaceObjectAtIndex:page withObject:controller];
  [controller release];
 }

// 将控制器的视图添加到滚动视图 if (nil ==controller.view.superview) { CGRect框架=scrollView.frame; frame.origin.x =frame.size.width * 页; 框架.origin.y = 0; 控制器.view.frame = 框架; [scrollView addSubview:controller.view];//<<控制器和子视图 } // 看起来都是非空的 // 此时的有效值

这是 CBFullScreenViewController 中的 init 方法:

- (id)init {
 if ((self = [super initWithNibName:@"CBFullScreenViewController" bundle:nil])) {
  self.cover = [[UIImageView alloc] init];
  self.homeButton = [[UIButton alloc] init];
  self.tabView = [[UIButton alloc] init];
  self.closedSubtitleLabel = [[UILabel alloc] init];
  self.openSubtitleLabel = [[UILabel alloc] init];
    // <-- snip...more initialization --> //
 }
 return self;
}

虽然过去 2 小时的故障排除帮助我追踪了一些不相关的内存泄漏,但我一生都无法弄清楚我的值发生了什么'我进入我的视野!

哦,也许值得一提的是,我的每个网点都有@synthesize,而且它们都与 IB 挂钩。屏幕截图此处

Summary

I'm repurposing Apple's Page Control project. In loadScrollViewWithPage:, the view controllers that I'm adding to the scroll view appear on screen without their initialized values, as if displayed directly from the nib.

Specifics

Here's the code that appears to be working when I step through it:

 CBFullScreenViewController *controller = [viewControllers objectAtIndex:page];

 if ((NSNull *)controller == [NSNull null]) {
  controller = [[CBFullScreenViewController alloc] init];

  // Populate the view from the corresponding CBImage object
  CBImage *imageObject = [imageArray objectAtIndex:page];
  BOOL bookmarked = [imageObject.bookmarked boolValue];
  controller.bookmarkButton.highlighted = bookmarked;
  NSString *subtitle = imageObject.subtitle;
  controller.closedSubtitleLabel.text = subtitle;
     // <-- snip...more initialization --> //
  controller.delegate = self;

  [viewControllers replaceObjectAtIndex:page withObject:controller];
  [controller release];
 }

// add the controller's view to the scroll view
if (nil == controller.view.superview) {
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
controller.view.frame = frame;
[scrollView addSubview:controller.view];//<< controller and subviews
} // all have non-null, seemingly
// valid values at this point

Here's the init method in CBFullScreenViewController:

- (id)init {
 if ((self = [super initWithNibName:@"CBFullScreenViewController" bundle:nil])) {
  self.cover = [[UIImageView alloc] init];
  self.homeButton = [[UIButton alloc] init];
  self.tabView = [[UIButton alloc] init];
  self.closedSubtitleLabel = [[UILabel alloc] init];
  self.openSubtitleLabel = [[UILabel alloc] init];
    // <-- snip...more initialization --> //
 }
 return self;
}

While troubleshooting this for the last 2 hours has helped me track down some unrelated memory leaks, I can't for the life of me figure out what's happening to the values I'm putting into my view!

Oh, it's probably worth mentioning that I've got @synthesize for each of my outlets, and they're all hooked up in IB. Screenshot here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

知你几分 2024-09-07 08:11:30

几个小时后......

我的解决方案

如上所述,我终于找到了一条线索,直到我完成了按钮上的所有初始化之后,子视图的 viewDidLoad 才会触发等等,这意味着笔尖覆盖了我所有的初始化。

一种有效的解决方案是使滚动视图成为子视图的委托...

@interface CBScrollViewController : UIViewController
          <***CBFullScreenViewControllerDelegate***, UIScrollViewDelegate> {
...etc...

然后通过从子视图的 viewDidLoad 中调用委托中的函数来初始化所有内容。

CBFullScreenViewController.h

@protocol CBFullScreenViewControllerDelegate
- (UIImage *)imageForFullScreenView:(CBFullScreenViewController *)controller;
@end

CBScrollViewController.m

- (UIImage *)imageForFullScreenView:(CBFullScreenViewController *)controller {
    NSUInteger page = controller.pageNumber;
    CBImage *image = [imageArray objectAtIndex:page];
    UIImage *pixels = [CBDataAccess pixelsForImage:image];
    return pixels;
}

更好的解决方案

但最终,问题是架构上的。我实现它的第一种方法是,当每个视图都滑动到位时,我的所有控件都会被复制,这既丑陋又浪费。

上面的代码显示了我的子视图中除了 UIImageView 之外什么都没有,因为所有控件实际上只需要加载一次:在图像上一动不动地浮动。为单个全屏视图加载笔尖完全是多余的。

那么,更好的解决方案是使用 Interface Builder 来实现滚动视图的更复杂的布局,其中包含我拥有的按钮和滑动信息选项卡,但将 Interface Builder 排除在子视图之外,子视图可以轻松地以编程方式加载。

Hours later....

My solution

As noted above, I finally found a clue in that the sub-views' viewDidLoads weren't firing until after I'd done all my initialization on the buttons and whatnot, implying that the nib was overwriting all of my initialization.

One solution that worked was to make the scroll view a delegate of the subviews...

@interface CBScrollViewController : UIViewController
          <***CBFullScreenViewControllerDelegate***, UIScrollViewDelegate> {
...etc...

and then initialize everything by calling a function in the delegate from within the subview's viewDidLoad.

CBFullScreenViewController.h

@protocol CBFullScreenViewControllerDelegate
- (UIImage *)imageForFullScreenView:(CBFullScreenViewController *)controller;
@end

CBScrollViewController.m

- (UIImage *)imageForFullScreenView:(CBFullScreenViewController *)controller {
    NSUInteger page = controller.pageNumber;
    CBImage *image = [imageArray objectAtIndex:page];
    UIImage *pixels = [CBDataAccess pixelsForImage:image];
    return pixels;
}

An even better solution

In the end, though, the problem was architectural. The first way I implemented it, all of my controls were duplicated as each view was swiped into place, which was both ugly and wasteful.

The code above shows how I ended up having nothing in my subviews other than a UIImageView because all of the controls really only needed to be loaded once: floating motionless over the image. Loading a nib for a single, full-screen view is total overkill.

The better solution, then, is to use Interface Builder for the scroll view's more complex layout with the buttons and sliding info tab that I had, but leave Interface Builder out of it for the subviews, which can just as easily be loaded programmatically.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文