2016-12-21 97 views
14

我有UINavigationControllerUITableViewController的子類。UINavigationController子類的便捷初始化使子類常量初始化兩次

要初始化子類,我決定使用一些調用超類的指定初始化方法的一些convenience init方法。此外,每個子類有一些let常數:

let someValue: SomeClass = SomeClass() 

每個類都成功地通過調用其新創建convenience init方法初始化。

問題是let常量被初始化TWICEUINavigationController子類中。

import UIKit 
import PlaygroundSupport 

final class Navigation: UINavigationController { 
    convenience init(anyObject: Any) { 
     self.init(rootViewController: UIViewController()) 
    } 
    let service = Constant("Constant Initialization -> Navigation") 
} 

final class Table: UITableViewController { 
    convenience init(anyObject: Any) { 
     self.init(style: .plain) 
    } 
    let service = Constant("Constant Initialization -> Table") 
} 

class Constant: NSObject { 
    init(_ string: String) { 
     super.init() 
     debugPrint(string) 
    } 
} 

Navigation(anyObject: NSNull()) 
Table(anyObject: NSNull()) 

我們是否允許使用上述的convenience init?爲什麼?

爲什麼convenience init行爲在這兩種情況下有所不同?

經過與:版本8.2β(8C30a)版本8.2(8C38)版8.2.1(8C1002)

P.S.以上代碼的遊樂場日誌:

"Constant Initialization -> Navigation" 
"Constant Initialization -> Navigation" 
"Constant Initialization -> Table" 

回答

3

所以這似乎是奇怪的「預期的行爲」與斯威夫特。它發生的原因是由於不斷初始化的屬性service。也就是說,這篇文章總結了您看到很好的問題:blog post

從本質上講,對象 - 潛在的超級類泄漏內存和service屬性,因爲這種模式的OBJ-C初始化的初始化兩次:

- (id)init { 
    self = [super init]; 
    if (self) { 
    self = [[self.class alloc] initWithNibName:nil bundle:nil]; 
    } 
    return self; 
} 

一個簡單的解決方案,以避免這種情況是以下模式:

import UIKit 

final class NavigationController: UINavigationController { 
    var service: ObjectTest? 

    convenience init() { 
     self.init(rootViewController: UIViewController()) 
     self.service = ObjectTest("init nav") 
    } 
} 
class ObjectTest: NSObject{ 
    init(_ string: String) { 
     super.init() 
     print(string) 
    } 
} 

所有這一切從你實現改變之後才初始化service喲我們的類本身被初始化。

不過,另一種解決方案是對初始化的超類使用指定的初始值設定項。這意味着你不使用便利的初始化器,它將採用上述的Obj-C初始化模式。

+0

謝謝你的回答。而且我仍然不明白爲什麼這兩種情況下的便利初始行爲是不同的? – iWheelBuy

+0

因此,'convenience'初始化使用上面的Objective-C示例init模式,其中有兩個init調用('[super init]'和'[self.class alloc] init ...]'。理解,會直接進入''[self.class alloc] init ...]'初始化程序路徑,因此不會雙重初始化,這就是導致您看到的問題的原因。 – BHendricks

+0

我認爲在這兩種情況下我打電話給指定的初始值,不是嗎? – iWheelBuy