2015-07-09 10 views
11

Bazı NSObject serbest bırakılmış bir NSPointerArray zayıf var. compact çağırmadan önce benim gördüğüm geçerli:NSPointerArray garip sıkıştırması

mantıklı ama gerçekten garip ben bu dizi üzerinde compact demenden aynı değerleri görmek olmasıdır
(lldb) po [currentArray count] 
1 
(lldb) po [currentArray pointerAtIndex:0] 
<nil> 
(lldb) po [currentArray allObjects] 
<__NSArrayM 0x16f04f00>(

) 

! Sayım hala 1 değerini döndürür ve pointerAtIndex:0 ise nil'dur.

Neden nil kaldırılmamış?

before compaction inside autorelease: testingPointer = <NSObject: 0x7de7ff80> count = 1, allObjects = (
    "<NSObject: 0x7de7ff80>" 
), pointerAtIndex:0 = <NSObject: 0x7de7ff80>, pointerAtIndex:0 class = NSObject 
2015-07-20 14:27:14.062 AppetizeSuite copy[54144:9019054] before compaction outside autorelease: testingPointer = (null) count = 1, allObjects = (
), pointerAtIndex:0 = (null), pointerAtIndex:0 class = (null) 
2015-07-20 14:27:22.615 AppetizeSuite copy[54144:9019054] after compaction outside autorelease: testingPointer = (null) count = 1, allObjects = (
), pointerAtIndex:0 = (null), pointerAtIndex:0 class = (null) 

Neden compact yöntem ilk işaretçisi silmez:

- (void)testCompaction { 
    __weak id testingPointer = nil; 

    NSPointerArray *weakArray = [NSPointerArray weakObjectsPointerArray]; 

    @autoreleasepool { 

     NSObject *someObj = [[NSObject alloc] init]; 

     testingPointer = someObj; 

     [weakArray addPointer:(__bridge void*)testingPointer]; 

     NSLog(@"before compaction inside autorelease: testingPointer = %@ count = %d, allObjects = %@, pointerAtIndex:0 = %@, pointerAtIndex:0 class = %@", testingPointer, [weakArray count], [weakArray allObjects], [weakArray pointerAtIndex:0], [(id)[weakArray pointerAtIndex:0] class]); 

     someObj = nil; 
    } 

    NSLog(@"before compaction outside autorelease: testingPointer = %@ count = %d, allObjects = %@, pointerAtIndex:0 = %@, pointerAtIndex:0 class = %@", testingPointer, [weakArray count], [weakArray allObjects], [weakArray pointerAtIndex:0], [(id)[weakArray pointerAtIndex:0] class]); 

    [weakArray compact]; 

    NSLog(@"after compaction outside autorelease: testingPointer = %@ count = %d, allObjects = %@, pointerAtIndex:0 = %@, pointerAtIndex:0 class = %@", testingPointer, [weakArray count], [weakArray allObjects], [weakArray pointerAtIndex:0], [(id)[weakArray pointerAtIndex:0] class]); 
} 

ve günlükleri:

DÜZENLEME

İşte tam kodu (evet bu XCTesting oluyor framework) var? compact'u aramadan önce açıkça bir nil.

+0

İşaretçi dizisine 'bırakılan bazı NSObject'leri nasıl eklediniz? Ve zayıfObjectsPointerArray kullanıyor musunuz? –

+0

@KazukiSakamoto Yukarıdaki güncellenmiş soruma bir göz atabilir misiniz? –

cevap

9

Bunun nedeni -compact'un, dahili bir flag 'needCompaction' ayarlanıp ayarlanmadığını kontrol etmesidir. Değilse, sadece erken boşalır. Bayrağın ayarlandığı tek zaman, bir nil işaretçisinin genel arabirim aracılığıyla doğrudan diziye eklenmesidir. İşaretçi diziye eklendikten sonra zayıf bir şekilde başvurulan bir nesnenin serbest bırakılması (ve işaretçinin geçersiz olması) durumunda ayarlanmaz.

Bu davranışa ilişkin bir çalışma, -compact numaralı telefonu aramadan önce diziye bir nil işaretçisini eklemesidir. İdeal değil ama işe yarayacak.

[pa addPointer:nil]; // forces the pointer array to do compaction next time 
[pa compact]; 
+0

Bu cevap için teşekkür ederiz. Benim için çok yararlı oldu. –

İlgili konular