2011-10-22 45 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

相關問題