2011-10-22 29 views
2

我想为UIViewController构建一个自定义的初始化方法,但是在互联网上进行了深入研究后,特别是在SO中,我对指定的初始化程序感到困惑。如何编写防止viewDidLoad被调用的自定义初始化程序?

我有一个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:]而被调用,它不初始化UIImageView,因为self.filename为空。

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

我怎样才能确保viewDidLoad:是呼叫initWithFilename:initWithNibNameOrNil:bundle:之间initWithFilename:而不是之后?

如果这不可行,我该如何实现一个接收自定义数据以创建和定制视图的初始化方法?

谢谢!

+0

如何定义文件名?宣称的财产或定制配件? – logancautrell

+0

'filename'被定义为'@property(strong,nonatomic)NSString * filename;'在'WallpaperDetailsViewController'的'@interface'声明中# – elitalon

+2

正在导致视图加载的init代码中发生了一些事情。设置一个中断点,看看有没有负载,看看为什么它被调用提前。 – logancautrell

回答

2

我发现了这个问题。

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

问题是什么?我已初始化父级的initWithNibName方法中的子视图,而不是遵循延迟加载技术,并在viewDidLoad中执行。当WallpaperDetailsViewController正在调用其父母初始值设定项时,它变得杂乱,并导致viewDidLoad无法正常工作。

解决方案?我将父类中的每个子视图初始化移至其viewDidLoad方法,并保持我的原始实现WallpaperDetailsViewController完整。现在一切正常按预期工作

感谢@Josh Caswell和@logancautrell

+0

很高兴你知道了。我想我的答案有点不合时宜,但很明显,解决方案存在于您发布的代码之外的代码中。 –

+0

对我也很好 – VTS12

0

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

或者,也可以将view属性中的UIImage属性设置为viewWillAppear:而不是viewDidLoad。

+0

当然这是一种替代解决方案,但我想了解其行为:) – elitalon

0

首先,不建议您在初始化程序中使用点语法。看到一些很好的讨论如下:

Objective-C Dot Syntax and Init

其次,你可以做的是在分配给您的初始形象为好。所以,你可以做沿着

- (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中被调用之前。

祝你好运!

+2

无需在视图控制器的初始化方法中创建图像视图。事实上,如果VC收到内存警告,可能会造成麻烦。最好坚持延迟加载范例,只在需要时分配它,在'loadView:'或'viewDidLoad:' –

1

你不需要那个空的执行initWithNibName:bundle:。此外,它看起来像你的类这里建立其指定的初始化是initWithFilename:如果这是真的,initWithFilename:应该调用父类的DI:

- (id) initWithFilename:(NSString *)aFilename { 
    // Call super's designated initializer 
    self = [super initWithNibName:@"WallpaperDetailsViewController" 
         bundle:nil]; 
    if (self) { 
    self.filename = aFilename; 
    } 
    return self; 
} 

的规则是所有初始化类应该调用类的DI和DI本身应该称为超级的D.I.

从您发布的内容中不完全清楚为什么loadView:在初始化程序完成之前被调用。 Logancautrell的评论建议在视图加载方法中设置断点是很好的。

+0

其实我认为,但在这种情况下它不适用于我。这就是为什么在问这里之前我已经把头靠在墙上。 – elitalon

+0

什么“不起作用”? –

+0

'UIImageView'没有正确创建,因为在设置'self.filename = aFilename'之前调用了viewDidLoad。 – elitalon

相关问题