Objective-C'de bir sınıfın bir örneğini @protocol'a yayınlayın


102

Tanımladığım bir protokole uyan veya uymayan bir nesnem (bir UIViewController) var.

Nesnenin protokole uygun olup olmadığını belirleyebileceğimi biliyorum, ardından yöntemi güvenle çağırın:

if([self.myViewController conformsToProtocol:@protocol(MyProtocol)]) {
    [self.myViewController protocolMethod]; // <-- warning here
}

Ancak, XCode bir uyarı gösterir:

warning 'UIViewController' may not respond to '-protocolMethod'

Bu uyarıyı önlemenin doğru yolu nedir? Sınıf self.myViewControllerolarak rol alamıyorum MyProtocol.

Yanıtlar:


172

Bunu yapmanın doğru yolu şunları yapmaktır:

if ([self.myViewController conformsToProtocol:@protocol(MyProtocol)])
{
        UIViewController <MyProtocol> *vc = (UIViewController <MyProtocol> *) self.myViewController;
        [vc protocolMethod];
}

UIViewController <MyProtocol> *Tipi döküm çevirir kullanarak ise "vc MyProtocol için uygundur bir UIViewController amacı," id <MyProtocol>çevirir "vc bilinmeyen bir sınıfı bu MyProtocol için uygundur bir amacı,".

Bu şekilde, derleyici size uygun tip kontrolü verecektir vc- derleyici size sadece herhangi bir yöntemde bildirilmemiş UIViewControllerveya <MyProtocol>çağrılmışsa bir uyarı verecektir . idsadece çevrilecek nesnenin sınıfını / türünü bilmiyorsanız kullanılmalıdır.


2
Protokolleri kullanırken gerçekten nesne tipini önemsememelisiniz - bir protokolün bütün noktası, herhangi bir nesne türünün onu benimseyebilmesi ve belirli bir nesneye dönüştürmek zorunda kalmadan kullanılabilmesidir. Bu yüzden, yukarıdaki yerine bir protokole çevirdiğiniz her yerde @andy tarafından verilen cevabı kullanmanızı tavsiye ederim - id<MyProtocol> p = (id<MyProtocol>)self.myViewController;Bu cevap ve @andys her ikisi de doğru, ancak onunki daha doğrudur.
memmons

2
@Answerbot yorumunuz yanlış ve cevabımın son paragrafında belirttiğim noktayı kaçırıyor. Nesne türü sizin için önemli olabilir veya olmayabilir, duruma göre değişir. Ne bir mesaj ilan göndermek istediğiniz olur UIViewControllerüzere vccevabım örnekte ve bu ilan ediyor id <MyProtocol>?
Nick Forge

Yorumumla ilgili neyin yanlış olduğundan emin değil misiniz? Her durumda, bir nesnenin bir protokole uygun olup olmadığını kontrol ediyorsanız, neden o zaman protokole bağlı olmayan başka bir yöntemi çağırasınız? Bunu yapmak zorunda olduğumu veya bunu incelediğim kodda gördüğümü hatırlayamıyorum. Bana bir kod kokusu gibi görünüyor.
memmons

Onu görmemiş / kullanmamış olmanız, bunun bir kod kokusu olduğu anlamına gelmez. Tür bilgilerini kullanarak atmanınid bir sorun olduğu bir örneği gösteren kod parçacığı : gist.github.com/nsforge/7743616
Nick Forge

60

Bunu şu şekilde yayınlayabilirsiniz:

if([self.myViewController conformsToProtocol:@protocol(MyProtocol)])
{
    id<MyProtocol> p = (id<MyProtocol>)self.myViewController;
    [p protocolMethod];
}

Bu beni de biraz şaşırttı. Objective-C'de, protokol türün kendisi değildir, bu nedenle istediğiniz protokolle birlikte id(veya başka bir tür) belirtmeniz gerekir NSObject.


Ah, harika, teşekkürler. Sadece kontrol ettim ve onu yayınlamanın da (id)işe yaradığını gördüm . Bu kötü bir biçim mi?
Ford

1
Bunu id <MyProtocol> olarak atarsanız, o protokolde tanımlanmamış yöntemler kullanırsanız derleyici sizi uyaracaktır.
dreamlax

1
@dreamlax - Bu, derleyicinin protokollere karşı tür denetimi yapma şeklidir. Daha fazla bilgi için developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/… adresine bakın .
Andy

1
@Ford - protokolü özel olarak kullanmak daha iyi olur, çünkü bu şekilde derleyici sizin için bazı tür kontrolleri yapabilir.
Andy

1
@Andy, 'id' zaten bir işaretçi olduğundan '*' işaretine ihtiyacın olduğunu sanmıyorum. Yani: id <MyProtocol> p = (id <MyProtocol>) self.myViewController; [p protocolMethod]; Veya sadece: [(id <MyProtocol>) self.myViewController protocolMethod];
Ford
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.