2014-10-03 7 views
27

Kullanılması Bu yeni makro XCode 6'da tanıtılıyor var.iOS Belirlenmiş başlatıcıları: Ben net arandı NS_DESIGNATED_INITIALIZER</p> <p>, ama gerçekten bu nasıl kullanılacağı konusunda herhangi bir iyi belgelerine bulamadı: NS_DESIGNATED_INITIALIZER

Sözdizimsel olarak, bunun gibi kullanabilirsiniz:

- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER; 

Ama bu makro ile bir başlatıcı işaretleme olası avantajları nelerdir ve aynı zamanda bu kullanırken biz görünümlü olmalıdır şeyler nelerdir?

Bu makronun kullanım durumları ile ilgileniyorum. Herhangi bir link/dokümantasyon takdir edilecektir.

cevap

44

NS_DESIGNATED_INITIALIZER kullanımı güzel http://useyourloaf.com/blog/2014/08/19/xcode-6-objective-c-modernization.html açıklanmıştır:

The designated initializer guarantees the object is fully initialised by sending an initialization message to the superclass. The implementation detail becomes important to a user of the class when they subclass it. The rules for designated initializers in detail:

  • A designated initializer must call (via super) a designated initializer of the superclass. Where NSObject is the superclass this is just [super init].
  • Any convenience initializer must call another initializer in the class - which eventually leads to a designated initializer.
  • A class with designated initializers must implement all of the designated initializers of the superclass.

Örnek olarak, arayüz

@interface MyClass : NSObject 
@property(copy, nonatomic) NSString *name; 
-(instancetype)initWithName:(NSString *)name NS_DESIGNATED_INITIALIZER; 
-(instancetype)init; 
@end 

sonra derleyici olup olmadığını kontrol eder, eğer çağıran init (kolaylık) başlatıcı (atanmış) başlatıcı initWithName:, bu nedenle bir uyarı neden olur:

-(instancetype)init 
{ 
    self = [super init]; 
    return self; 
} 

ve bu Tamam olurdu: yaklaşık

-(instancetype)init 
{ 
    self = [self initWithName:@""]; 
    return self; 
} 

yılında Swift kurallar belirlenmiş ve belirlenen Amaç işaretleme, Objective-C ve Swift kodu karıştırın eğer kolaylık ilklendiriciler daha sıkı, ve -C başlatıcılar, derleyicinin kuralları zorlamasına yardımcı olur.

Örneğin, bu Swift alt bir derleyici hatası vardır:

class SwClass: MyClass { 
    var foo : String 
    init(foo : String) { 
     self.foo = foo 
     super.init() 
    } 
} 

ve bu Tamam olacaktır:

class SwClass: MyClass { 
    var foo : String 
    init(foo : String) { 
     self.foo = foo 
     super.init(name: "") 
    } 
} 
+2

Objective-C'deki konsept ile çok iyi düşünülmüş çünkü initWithName: @ "" alt sınıflandırmada her zaman mantıklı değil. Bunun yerine, normal sınıf üst üste atanan atanmış üst sınıftan, alt sınıftan atanmış başlatıcıyı kullanmak için söyleyerek istisna atmalıdır. – Andy

+5

Martin'in cevabına eklemek için, kullanıcının varsayılan başlatıcıları çağırmasını tamamen iptal etmek isteyebilirsiniz, bu durumda aşağıdakileri kullanabilirsiniz: - (instancetype) init NS_UNAVAILABLE; –

1

atanmış başlangıç ​​sınıflara, bizim başlatıcıları yapı şeklini belirlemek; onlar sınıfınız için “canonical initializer”. Seçtiğiniz süper sınıf zincirindeki başlatılmış başlatıcıdan bağımsız olarak güvenilir olmayı garanti eder ve her zaman en uzak atadan en uzak olana kadar gider.

Belirtilen bir başlatıcı, bir nesne oluştururken hangi başlatıcıyı kullanmanız gerektiğini tanımlamaz. https://blog.twitter.com/2014/how-to-objective-c-initializer-patterns'da çok açıklanmıştır. Bunu yapmak için

6

Benim en yaygın yolu:

@interface Person : NSObject 

- (nullable instancetype)initWithName:(nonnull NSString *)name NS_DESIGNATED_INITIALIZER; 
- (nullable instancetype)init NS_UNAVAILABLE; 

@property (nonatomic, nonnull) NSString *name; 

@end 

Ve uygulama (Bu durumda NSObject 'ın init:) senin sınıf yönteminin NS_DESIGNATED_INITIALIZER geçersiz kılmak gerekir Bu durumda

@implementation Person 

- (instancetype)initWithName:(NSString *)name 
{ 
    self = [super init]; 
    if (self) { 
     self.name = name; 
    } 
    return self; 
} 

@end 

- Bu yöntemi gereksiz olarak işaretlemek için NS_UNAVAILABLE kullandık.Ya da varsayılan parametreler ile atanmış başlatıcınızı çağırmak için bunu geçersiz kılabilirsiniz.

İlgili konular