2013-03-20 14 views
7

...Bloklar döngüyü adlandırma kuralından koruyor mu? Aşağıdaki davranış bulmak için şaşırıyorum

@interface Foo : NSObject 

- (void)addBar:(id)aBar withCompletion:(void(^)(void))completion; 

@end 

@interface AwesomeClass : NSObject 

@property (strong, nonatomic) Foo *foo; 

- (void)doSomethingWithBar:(id)bar; 

@end 

@implementation AwesomeClass 

- (void)doSomethingWithBar:(id)bar 
{ 
    [self.foo addBar:bar withCompletion:^{ 
     NSLog(@"%@", self.foo); 
    }]; 
} 

Xcode 4.6.1 yılında şiddetle bu blokta "Yakalama 'öz' bir yol açması muhtemel olduğunu -doSomethingWithBar: uygulanmasında bir uyarı olsun döngüsü koru. " Ben -setupBar:withCompletion: için yöntemin -addBar:withCompletion: arasında adını planı ayrı eğer

Ancak bu uyarı uzağa gider. Görünen o ki benim sürprizim, Objective-C adlandırma kurallarına dair bilgimde bir boşluk var.

+1

Yeniden derlenmeyi deneyin. Uyarı, Xcode'un aptalca olduğu ve LLVM'nin son kez üretilen uyarıları ortadan kaldırdığı kadar "gitmekten" vazgeçmiyor – CodaFi

cevap

19

[self.foo someMethod:bar withCompletion:^{ 
    NSLog(@"%@", self.foo); 
}]; 

genellikle korumak döngüsü yaratmaz kodu. someMethod:withCompletion: sadece bloğu çağırır ve geri dönerse, hiç bir tutma döngüsü yoktur. (-[NSArray enumerateObjectsUsingBlock:] bir örnektir.)

Yalnızca someMethod:withCompletion: "yürütülecek bloğu" hatırlarsa, olası bir tutma döngüsü vardır. Bu yüzden clang, bloğun daha sonra çalıştırılması için bloğu Foo özelliğine kaydeden "ayarlayıcı benzeri" bir yöntem olup olmadığına karar vermek için bir sezgisel kullanır. Bir özelliği ayarlamak veya bir (çok) ilişkiye bir değer eklemek için Anahtar-Değer Kodlaması'nda erişim kalıpları olan

Bu

Clang source code görülebilir:

/// Check for a keyword selector that starts with the word 'add' or 
/// 'set'. 
static bool isSetterLikeSelector(Selector sel) { 
    if (sel.isUnarySelector()) return false; 

    StringRef str = sel.getNameForSlot(0); 
    while (!str.empty() && str.front() == '_') str = str.substr(1); 
    if (str.startswith("set")) 
    str = str.substr(3); 
    else if (str.startswith("add")) { 
    // Specially whitelist 'addOperationWithBlock:'. 
    if (sel.getNumArgs() == 1 && str.startswith("addOperationWithBlock")) 
     return false; 
    str = str.substr(3); 
    } 
    else 
    return false; 

    if (str.empty()) return true; 
    return !islower(str.front()); 
} 

burada denir: "set" çünkü setupBar yöntemi "setter benzeri" yöntemi olarak muamele değil

/// Check a message send to see if it's likely to cause a retain cycle. 
void Sema::checkRetainCycles(ObjCMessageExpr *msg) { 
    // Only check instance methods whose selector looks like a setter. 
    if (!msg->isInstanceMessage() || !isSetterLikeSelector(msg->getSelector())) 
    return; 

    /* 
    * rest omitted 
    */ 

} 

olduğunu

büyük harfle takip edilmez.