2016-04-11 21 views
0

Sınıf yöntemi olarak başlatma geçerli:Sözdiziminin yanı sıra, bir başlatma yöntemi yazmak için örnek veya sınıf yöntemi olarak bir fark var mıdır? İşte

+ (instancetype)imageEditorForDocument:(ImageDocument*)imageDocument 
{ 
    ImageEditorViewController* result = nil; 
    result = [[ImageEditorViewController alloc] initWithNibName:@"ImageEditorViewController" 
                 bundle:[NSBundle mainBundle]]; 

    if (result) 
    { 
     result.imageDocument = imageDocument; 
    } 
    return result; 
} 

Ve burada örnek yöntemi olarak bir başlatma geçerli:

- (instancetype)initWithDocument:(ImageDocument *)imageDocument 
{ 
    self = [[ImageEditorViewController alloc] initWithNibName:@"ImageEditorViewController" 
                 bundle:[NSBundle mainBundle]]; 

    if(self) 
    { 
     self.imageDocument = imageDocument; 
    } 
    return self; 
} 
Bildiğim kadarıyla söyleyebilirim

, tek fark gönderen kokan olmasıdır

Bir sınıf başlatıcısı kullanıldığında alloc numaralı telefonu aramam gerekiyor. Ama başka bir neden var mı?

Ayrıca, bir yan soru bir sınıf yöntemi olan bir başlatıcı için bir ad var mı? manüel referans sayımı (MRC) ile NSColor

+ (NSColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha NS_AVAILABLE_MAC(10_9); 
+1

Fabrika yöntemidir. – rmaddy

cevap

2

içinde gibi, fark Örnek yöntemi arayan hemen sahip olduğu bir örneği döndüğü fabrika yöntemi tipik olarak bir autoreleased örneği döndürüldü.

Otomatik referans sayma (ARC) ile, bu fark çağrı kodundan gizlendi.

Tek fark, arayan için kolaylık ve sınıfın yazarının isteğe bağlı fabrika yöntemini yazması için biraz daha fazla çalışma olmasıdır.

BTW - örnek yöntem başlatıcınız yanlış.

- (instancetype)initWithDocument:(ImageDocument *)imageDocument 
{ 
    self = [super initWithNibName:@"ImageEditorViewController" 
          bundle:[NSBundle mainBundle]]; 

    if(self) 
    { 
     self.imageDocument = imageDocument; 
    } 

    return self; 
} 

Ve bunlar dikkate alındığında, sizin fabrika yöntem gerçekten olmalıdır:

+ (instancetype)imageEditorForDocument:(ImageDocument*)imageDocument 
{ 
    ImageEditorViewController* result = [[[self class] alloc] initWithDocument:imageDocument]; 

    return result; 
} 
+0

Teşekkürler rmaddy :) Ve yanlış kodda yanlış kodlarım var - Aslında sadece fabrika yöntemini yapıştırdım ve örneğini başlatmaya benzedim - değiştirdim ama bu kısmı göz ardı ettim. Düzeltme için teşekkürler ^^ –

+0

Son güncellemeye bakın. Fabrika yönteminiz de yanlıştı. – rmaddy

+0

Örnek başlatıcı geçerli kodumuzda mevcut değil. Yani, örnek başlatıcı yöntemini oluşturduğumu ve sonra bunu çağırmak için fabrika yöntemini değiştirdiğimi mi öneriyorsunuz? –

1

Evet büyük bir fark vardır O (self belirlememeyi uygun yolu) bu gibi olmalıyım. Bir fabrika yöntemi (sınıf yöntemi) uygularsanız, örneğin yeni bir örnek oluşturmak yerine, nesnenizin halihazırda var olan bir örneğini (örneğin, bir çeşit önbellekten) döndürmeyi seçebilirsiniz. Başlamak için pahalı olan bir sınıf Country olduğunu düşünün. Öte yandan

+(instancetype) countryForCountryCode: (NSString *)countryCode 
{ 
    Country *country = ... // ask our "CountryCache" if we already have a cached instance of the country 
    if (!country) { 
     country = [[Country alloc] init]; 
     // Here you would also set up the new Country object, or even write a "private" initializer 
     // You would also add the new instance to the cache here 
    } 
    return country; 
} 

, bir "geleneksel" seçim arayan başlatıcısı: Dolayısıyla, birinci ve buna yeni bir nesne oluşturur ülkeyi bulmazsa sadece önbelleği arar aşağıdaki fabrika yöntem yazmak başlatıcınız çağrılmadan önce her zaman yeni bir örnek oluşturarak alloc aracılığıyla önbelleğe alınmış bir nesne döndürme yönteminiz olmayacaktır.

Son olarak kalıcı nesnelerle uğraştığımda (CoreData kullanmıyorsa) kişisel olarak fabrika yöntemlerini kullandığımı hatırlıyorum. Öyleyse, veritabanından yeni bir nesne almak istiyorsam, genellikle "yük" adı verilen bir fabrika yöntemi uygularım. Ve aslında veritabanında yeni bir kayıt oluşturmak için "oluştur" adlı başka bir fabrika yöntemi uygulayacağım. Burada başlatıcıları kullanırsanız, çok kafa karıştırıcı olur.

+0

Anladığımdan emin değilim.Kesim doğru geliyor, ama tamamen orada değilim Bir örnek başlatıcıda önbelleğe alınmış bir nesneyi döndürmekten vazgeçen nedir? '[Süper init]' 'i çağırmadan önce, bir kontrol yapılmadı ve varsa önbelleğe alınmış nesneyi döndürdünüz mü? –

+0

Bana ne geliyor? örnek başlatıcı Ben arayanın "tahsis" ile yarattığı yeni örnekte zaten "in". Pratik olarak, başka bir nesneyi "self" olarak atamam gerekecek, bu izin verilmiyor. – Lasse

+0

@AO Cevabımı çok umarım düzenledim benim nokta şimdi daha açık – Lasse

İlgili konular