2016-12-21 5 views
14

私はUINavigationControllerUITableViewControllerのサブクラスを持っています。UINavigationControllerの便利な初期化サブクラスはサブクラス定数initを2回作成します

サブクラスを初期化するために、いくつかのconvenience initメソッドを使用してスーパークラスの初期化子を呼び出すことにしました。

let someValue: SomeClass = SomeClass() 

各クラスが正常に新しく作成されたconvenience initメソッドを呼び出すことによって初期化されます。また、各サブクラスは、いくつかのlet定数を有します。

問題が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を使用できますか?どうして?

なぜこれらの2つのケースでconvenience initの動作が異なるのですか?

でチェック:バージョン8.2ベータ(8C30a)バージョン8.2(8C38)バージョン8.2.1(8C1002)

P.S.上記のコードの遊び場ログ:

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

答えて

3

これはSwiftの「期待される動作」のようです。それが起こっている理由は、一定の初期化されたプロパティserviceが原因です。すなわち、この記事はあなたがかなりよく見て問題を要約したものです。blog post

は基本的に、OBJの-C根底にあるスーパークラスがメモリをリークしているし、あなたの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を初期化されて、あなたの実装から変更だとよurクラス自体が初期化されます。

しかし、別の解決方法は、指定した初期化子をスーパークラスの初期化に使用することです。上記のObj-C初期化パターンを使用する便利な初期化子を使用しないことを意味します。

+0

ありがとうございました。そして、私はまだ利便性のinitの動作が2つのケースで異なっている理由を理解していませんか? – iWheelBuy

+0

''利便性 '初期化は上記のObjective-Cの初期化パターンを使用します。ここでは2つのinit呼び出し(' [super init] 'と' [self.class alloc] init ...] 'があります。理解して、 '[self.class alloc] init ...]'イニシャライザパスに直接入りますので、あなたが見ている問題の原因となっている初期化をダブルにしません。 – BHendricks

+0

私は両方のケースで私は指定されたイニシャライザを呼びますか? – iWheelBuy

関連する問題