2011-08-24 12 views
8

Aşağıdaki kod kilitlenir, çünkü son satır sentence içeriğinin son bloğu çıktığı zaman kaybolur.Bir bloğun dışındaki değişkene nesne atama

#import <Foundation/Foundation.h>  
int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    // simple block test - just iterate over some items and 
    // add them to a string 
    NSArray *items = [NSArray arrayWithObjects:@"why ", @"must ", @"this ",nil]; 
    __block NSString *sentence = @""; 
    [items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) 
    { 
     sentence = [sentence stringByAppendingFormat:@"%@",obj]; 
    }]; 
    // crash! 
    NSLog(@"Sentence is %@",sentence); 
    [pool drain]; 
    return 0; 
} 

Bu çalışmanın doğru/deyimsel yolu nedir? Orada oluyor ancak bu arada sen de belirtildiği gibi size

+0

Wow, bu garip, bunun neden çalışmadığından emin değilim. – jtbandes

+0

İnsanların bir şeyleri geri döndürmek için blokların sonunda bir [[bazı Değişkeni rehin tutmama] otomatikleştirmesi] yaptığını gördüm, ancak bir otorit havuzunun çalıştığından şüphelenirsem bunun neden bir fark yarattığından emin değilim. Yine de bilmiyorum, bu yüzden soruyorum ve blokları kopyalayıp etrafta dolaşan her tür eşya var, ama basit olması gereken bir şeyde bulabileceğim hiçbir şey yok. –

+0

Aldığınız hata/istisna nedir? – nacho4d

cevap

4

Tamam, gittim ve Xcode ile biraz oynadım, ve işte neler olduğuyla ilgili bir model var. O dealloc nesneler alloc'ed çağrılacak neden ne gibi görünüyor, ama bloğunun içinde autoreleased böylece

Yukarıda kullanılan blok özel hiçbir şey yapmıyor

ancak enumerateObjectsUsingBlock kodu NSAutoreleasePool kendi gibi görünüyor.

Aşağıdaki kod yukarıda gördüğüm şey davranış ile eşleşen Ben innerPool nesneyi kaldırırsanız Aslında beklendiği gibi

#import <Foundation/Foundation.h> 
int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    // simple block test - just iterate over some items and 
    // add them to a string 
    typedef void (^AccArrayBlock)(id obj, int idx, BOOL *stop); 
    // items to 'process' 
    NSArray *items = [NSArray arrayWithObjects:@"why ", @"must ", @"this ",nil]; 
    int idx = 0; 
    BOOL doStop = NO; 
    // make sentence mutable, so we can assign it inside block 
    __block NSString *sentence = @""; 
    // make a similar block to what we'd pass to enumerate... 
    AccArrayBlock myBlock = ^(id obj, int idx, BOOL *stop) 
    { 
     // returns and assigns an autoreleased string object 
     sentence = [sentence stringByAppendingFormat:@"(%d) %@ ",idx,obj]; 
    }; 
    // enumerate items and call block 
    for (NSString *item in items) { 
     // create a pool to clean up any autoreleased objects in loop 
     // remove this line, and the sentence will be valid after loop 
     NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init]; 
     myBlock(item, idx++, &doStop); 
     // drain the pool, autorelease objects from block 
     [innerPool drain]; 
     if (doStop) { 
      break; 
     } 
    } 
    // faults if we drained the pool 
    // Program received signal: “EXC_BAD_ACCESS”. 
    NSLog(@"Sentence is %@",sentence); 
    [pool drain]; 
    return 0; 
} 

, ardından kod çalışır ve muhtemelen NSRunLoop havuz sonunda temizler çeşitli NSString nesneleri.

NOT:

Google 'enumerateObjectsUsingBlock+autorelease'

ilk sonuç bu cevabı onaylar: Bu iş parçacığı şimdi 'enumerateObjectsUsingBlock autorelease' sayısının 2 hakkında sonucudur. Hepinize teşekkürler.

1

Tamam, bu şüpheli autorelease havuzu çalışırken, muhtemelen enumerateObjectsUsingBlock:'da olduğu gibi çöküyor. Bu, __block değişkeniniz varsa, çalışmak için can sıkıcı olacaktır. Bunun yerine bir NSMutableString kullanın veya basitçe temizleyici zaten olan yapabilirsiniz: Eğer ARC kullanırsanız

for (id obj in items) 
{ 
    sentence = [sentence stringByAppendingFormat:@"%@",obj]; 
} 

Alternatif, derleyici sizin için sorunu ortadan kaldırmak gerekir.

+1

Bu durumda bence '__blok' değiştiricisine gerek yok. Ve elbette [cümle yayınını] unutmayın 0 – nacho4d

+0

Ah evet iyi ikisini de yakala –

+0

Teşekkürler, ben başka bir yerde böyle bir şey kullandım, ama tahsis edilen nesneleri nasıl elde etmeye çalışıyorum bir blokta, bir bloktan uzaklaşırlar. Yukarıdaki kod, anlamadığım bir şeyi göstermek için düşünebildiğim en basit şey.Elbette 'NSMutableString' kullanarak bu şekilde kod yazmak daha verimli, ama ben sadece basit bir demo kodu istedim. Teşekkürler. –

1

nacho4d @ için

NSArray *items = [NSArray arrayWithObjects:@"why ", @"must ", @"this ",nil]; 
NSMutableString *sentence = [[NSMutableString alloc] init]; 
[items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) 
{ 
    [sentence appendFormat:@"%@",obj]; 
}]; 

NSLog(@"Sentence is %@",sentence); 

[sentence release]; sentence = nil; 

Güncelleme sayesinde değiştirirseniz çalışır ne% 100 emin değilim bu yüzden