Objective c 如何编写防止调用viewDidLoad的自定义初始值设定项?

Objective c 如何编写防止调用viewDidLoad的自定义初始值设定项?,objective-c,uiviewcontroller,initialization,ios5,Objective C,Uiviewcontroller,Initialization,Ios5,我想为UIViewController构建一个定制的init方法,但是在互联网上,特别是在中,我对指定的初始值设定者感到困惑 我有一个UIViewController的子类,其中有两个初始值设定项: - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]

我想为
UIViewController
构建一个定制的init方法,但是在互联网上,特别是在中,我对指定的初始值设定者感到困惑

我有一个
UIViewController
的子类,其中有两个初始值设定项:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  if ( self ) {

  }
  return self;
}

- (id) initWithFilename:(NSString *)aFilename {
  self = [self initWithNibName:@"WallpaperDetailsViewController" bundle:nil];
  if ( self ) { 
    self.filename = aFilename;
  }
  return self;
}
然后我有一个
viewDidLoad
方法,它根据
filename
属性自定义视图:

- (void)viewDidLoad {
  [super viewDidLoad];

  // Create a UIImageView to display the wallpaper
  self.wallpaper = [[UIImageView alloc] initWithImage:[UIImage imageNamed:self.filename]];
  // ...
}
在另一个
UIViewController
中,我进行以下调用:

WallpaperDetailsViewController *detailsViewController = [[WallpaperDetailsViewController alloc] initWithFilename:@"foobar.png"];
[[self navigationController] pushViewController:detailsViewController animated:YES];
结果是调用
viewDidLoad
是由于
[self initWithNibName:][/code>没有初始化
UIImageView
,因为
self.filename
为空

根据其他SO问题和答案,这应该是预期的行为。我不确定这一点,因为我在iOS 5之前的其他项目中有自己的经验。我的问题是:

如何确保
viewDidLoad:
initWithFilename:
之后调用,而不是在
initWithFilename:
initWithNibNameOrNil:bundle:
之间调用

如果不可能,如何实现接收自定义数据的初始值设定项方法来创建和自定义视图


谢谢

为什么不为filename属性使用一个自定义setter,在每次设置文件名时初始化UIImage


或者,也可以从ViewWillDisplay中的filename属性设置UIImage:而不是viewDidLoad。

首先,不建议在初始值设定项中使用点语法。请参阅以下内容,了解一些有益的讨论:

其次,您可以做的是在初始值设定项中指定图像。所以你可以按照

- (id) initWithFilename:(NSString *)aFilename {
   self = [self initWithNibName:@"WallpaperDetailsViewController" bundle:nil];
   if ( self ) { 
      filename = [aFilename retain];
      wallpaper = [[UIImageView alloc] initWithImage:[UIImage imageNamed:aFileName]];
   }
   return self;
}
这将允许您在调用viewDidLoad之前将所有内容设置好并处于良好状态


祝你好运

您不需要
initWithNibName:bundle:
的空实现。此外,这里的类似乎正在将其指定的初始值设定项设置为
initWithFilename:
如果这是真的,
initWithFilename:
应该调用超类的D.I.:

- (id) initWithFilename:(NSString *)aFilename {
  // Call super's designated initializer
  self = [super initWithNibName:@"WallpaperDetailsViewController" 
                         bundle:nil];
  if ( self ) { 
    self.filename = aFilename;
  }
  return self;
}
规则是类中的所有初始值设定项都应该调用类的D.I.,而D.I.本身应该调用超类的D.I


从您发布的内容来看,还不完全清楚为什么在初始值设定项完成之前调用
loadView:
。Logancautrell建议在视图加载方法中设置断点的评论很好。

我发现了这个问题

wallperdetailsviewcontroller
不是直接从
UIViewController
继承,而是从我实现的另一个自定义
UIViewController
继承

问题是什么?我已经在父对象的
initWithNibName
方法中初始化了一个子视图,而不是遵循延迟加载技术,在
viewDidLoad
中进行初始化。当
wallperdetailsviewcontroller
调用其父初始值设定项时,它变得混乱,导致
viewDidLoad
无法正常工作

解决方案是什么?我将父类中的每个子视图初始化都移动到了它的
viewDidLoad
方法,并保持了
wallpDetailsViewController
的原始实现完好无损。现在一切都按预期进行


感谢@Josh Caswell和@logancautrell

文件名是如何定义的?声明的属性或自定义附件?
文件名
的定义类似于
@property(强、非原子)NSString*文件名
@interface
壁纸详细信息viewcontroller
声明中,您的init代码中发生了导致加载视图的事件。在视图中设置一个断点并查看它为什么会被提前调用。当然,这是另一种解决方案,但我想了解其行为:)实际上我是这么想的,但在这种情况下它对我不起作用。这就是为什么我在问这个问题之前把头撞到墙上的原因。
UIImageView
没有正确创建,因为
viewDidLoad
是在设置
self.filename=aFilename
之前调用的。我想这是有道理的,因为在这种情况下
[super initWithNibName:@“…”bundle:nil];]
完全等同于在
self
上调用它。不需要在视图控制器的初始化方法中创建图像视图。事实上,如果VC收到内存警告,这可能会导致问题。最好坚持惰性加载模式,只在需要时分配它,在
loadView:
viewDidLoad:
很高兴你找到了它。我想我的答案有点旁敲侧击,但很明显,解决方案在于代码,而不是你发布的代码。