Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Modeler   Code  
»áÔ±   
 
   
 
 
     
   
 ¶©ÔÄ
  ¾èÖú
iOS ÖÐµÄ block ÊÇÈçºÎ³ÖÓжÔÏóµÄ
 
À´Ô´£ºÖйú´æ´¢ ·¢²¼ÓÚ 2016-9-5
  2209  次浏览      29
 

Block ÊÇ Objective-C ÖбÊÕß×îϲ»¶µÄÌØÐÔ£¬ËüΪ Objective-C ÕâÃÅÓïÑÔÌṩÁËÇ¿´óµÄº¯Êýʽ±à³ÌÄÜÁ¦£¬¶ø×î½üÆ»¹ûÍÆ³öµÄºÜ¶àÐ嵀 API ¶¼ÒѾ­¿ªÊ¼Ô­ÉúµÄÖ§³Ö block Óï·¨£¬¿É¼ûËüÔÚ Objective-C ÖбäµÃÔ½À´Ô½ÖØÒª¡£

ÕâÆªÎÄÕ²¢²»»áÏêϸ½éÉÜ block ÔÚÄÚ´æÖе½µ×ÊÇÒÔʲôÐÎʽ´æÔڵģ¬Ö÷Òª»á½éÉÜ block ÊÇÈçºÎ³ÖÓв¢ÇÒÊͷŶÔÏóµÄ¡£ÎÄÕÂÖеĴúÂë¶¼³ö×Ô Facebook ¿ªÔ´µÄ ÓÃÓÚ¼ì²âÑ­»·ÒýÓà µÄ¿ò¼Ü FBRetainCycleDetector £¬ÕâÊÇ·ÖÎö¸Ã¿ò¼ÜÎÄÕÂÖеÄ×îºóһƪ£¬Ò²ÊDZÊÕß¾õµÃ×îÓÐÒâ˼µÄÒ»²¿·Ö¡£

Èç¹ûÄãÏ£ÍûÁ˽â FBRetainCycleDetector µÄÔ­Àí¿ÉÒÔÔĶÁ ÈçºÎÔÚ iOS Öнâ¾öÑ­»·ÒýÓõÄÎÊÌâ ÒÔ¼°ºóÐøÎÄÕ¡£

Ϊʲô»á̸µ½ block

¿ÉÄܺܶà¶ÁÕß»áÓÐÕâÑùµÄÒÉÎÊ£¬±¾ÎļÈÈ»ÊÇ¶Ô FBRetainCycleDetector ½âÎöµÄÎÄÕ£¬ÎªÊ²Ã´»áÌáµ½ block£¿Ô­ÒòÆäʵºÜ¼òµ¥£¬ÒòΪÔÚ iOS ¿ª·¢Öдó¶àÊýµÄÑ­»·ÒýÓö¼ÊÇÒòΪ block ʹÓò»µ±µ¼Öµģ¬ÓÉÓÚ block »á retain Ëü³ÖÓеĶÔÏó£¬ÕâÑù¾ÍºÜÈÝÒ×Ôì³ÉÑ­»·ÒýÓã¬×îÖÕµ¼ÖÂÄÚ´æÐ¹Â¶¡£

ÔÚ FBRetainCycleDetector ÖдæÔÚÕâÑùÒ»¸öÀà FBObjectiveCBlock £¬Õâ¸öÀàµÄ - allRetainedObjects ·½·¨¾Í»á·µ»ØËùÓÐ block ³ÖÓеÄÇ¿ÒýÓã¬ÕâÒ²ÊÇÎÄÕÂÐèÒª¹Ø×¢µÄÖØµã¡£

- (NSSet *)allRetainedObjects {
NSMutableArray *results = [[[super allRetainedObjects] allObjects] mutableCopy];

__attribute__((objc_precise_lifetime)) id anObject = self.object;

void *blockObjectReference = (__bridge void *)anObject;
NSArray *allRetainedReferences = FBGetBlockStrongReferences(blockObjectReference);

for (id object in allRetainedReferences) {
FBObjectiveCGraphElement *element = FBWrapObjectGraphElement(self, object, self.configuration);
if (element) {
[results addObject:element];
}
}

return [NSSet setWithArray:results];
}

Õⲿ·Ö´úÂëÖеĴ󲿷ֶ¼²»ÖØÒª£¬Ö»ÊÇÔÚ¿ªÍ·µ÷Óø¸Àà·½·¨£¬ÔÚ×îºó½«»ñÈ¡µÄ¶ÔÏó°ü×°³ÉÒ»¸öϵÁÐFBObjectiveCGraphElement £¬×îºó·µ»ØÒ»¸öÊý×飬Ҳ¾ÍÊǵ±Ç°¶ÔÏó block ³ÖÓеÄÈ«²¿Ç¿ÒýÓÃÁË¡£

Block ÊÇʲô£¿

¶Ô block ÉÔ΢ÓÐÁ˽âµÄÈ˶¼ÖªµÀ£¬block ÆäʵÊÇÒ»¸ö½á¹¹Ì壬Æä½á¹¹´ó¸ÅÊÇÕâÑùµÄ£º

struct BlockLiteral {  
void *isa;
int flags;
int reserved;
void (*invoke)(void *, ...);
struct BlockDescriptor *descriptor;
};

struct BlockDescriptor {
unsigned long int reserved;
unsigned long int size;
void (*copy_helper)(void *dst, void *src);
void (*dispose_helper)(void *src);
const char *signature;
};

ÔÚ BlockLiteral ½á¹¹ÌåÖÐÓÐÒ»¸ö isa Ö¸Õ룬¶ø¶Ô isa Á˽âµÄÈËÒ²¶¼ÖªµÀ£¬ÕâÀïµÄ isa ÆäʵָÏòÁËÒ»¸öÀ࣬ÿһ¸ö block Ö¸ÏòµÄÀà¿ÉÄÜÊÇ __NSGlobalBlock__¡¢ __NSMallocBlock__ »òÕß __NSStackBlock__ £¬µ«ÊÇÕâЩ block£¬ËüÃǼ̳Ð×ÔÒ»¸ö¹²Í¬µÄ¸¸À࣬Ҳ¾ÍÊÇ NSBlock £¬ÎÒÃÇ¿ÉÒÔʹÓÃÏÂÃæµÄ´úÂëÀ´»ñÈ¡Õâ¸öÀࣺ

static Class _BlockClass() {  
static dispatch_once_t onceToken;
static Class blockClass;
dispatch_once(&onceToken, ^{
void (^testBlock)() = [^{} copy];
blockClass = [testBlock class];
while(class_getSuperclass(blockClass) && class_getSuperclass(blockClass) != [NSObject class]) {
blockClass = class_getSuperclass(blockClass);
}
[testBlock release];
});
return blockClass;
}
 

Objective-C ÖеÄÈýÖÖ block __NSMallocBlock__ ¡¢ __NSStackBlock__ ºÍ __NSGlobalBlock__ »áÔÚÏÂÃæµÄÇé¿öϳöÏÖ£º

| | ARC | ·Ç ARC | |------------|:----------------------------:|-----------------------------| | ²¶»ñÍⲿ±äÁ¿ | __NSMallocBlock__

__NSStackBlock__ | __NSStackBlock__ | | δ²¶»ñÍⲿ±äÁ¿ | __NSGlobalBlock__ | __NSGlobalBlock__ |

1.ÔÚ ARC ÖУ¬²¶»ñÍⲿÁ˱äÁ¿µÄ block µÄÀà»áÊÇ __NSMallocBlock__ »òÕß __NSStackBlock__ £¬Èç¹û block ±»¸³Öµ¸øÁËij¸ö±äÁ¿ÔÚÕâ¸ö¹ý³ÌÖлáÖ´ÐÐ _Block_copy ½«Ô­ÓÐµÄ __NSStackBlock__ ±ä³É __NSMallocBlock__ £»µ«ÊÇÈç¹û block ûÓб»¸³Öµ¸øÄ³¸ö±äÁ¿£¬ÄÇËüµÄÀàÐ;ÍÊÇ __NSStackBlock__ £»Ã»Óв¶»ñÍⲿ±äÁ¿µÄ block µÄÀà»áÊÇ __NSGlobalBlock__ ¼´²»ÔÚ¶ÑÉÏ£¬Ò²²»ÔÚÕ»ÉÏ£¬ËüÀàËÆ C ÓïÑÔº¯ÊýÒ»Ñù»áÔÚ´úÂë¶ÎÖС£

2.ÔÚ·Ç ARC ÖУ¬²¶»ñÁËÍⲿ±äÁ¿µÄ block µÄÀà»áÊÇ __NSStackBlock__ £¬·ÅÖÃÔÚÕ»ÉÏ£¬Ã»Óв¶»ñÍⲿ±äÁ¿µÄ block ʱÓë ARC »·¾³ÏÂÇé¿öÏàͬ¡£

Èç¹ûÎÒÃDz»¶Ï´òÓ¡Ò»¸ö block µÄ superclass µÄ»°×îºó¾Í»áÔڼ̳ÐÁ´ÖÐÕÒµ½ NSBlock µÄÉíÓ°£º

È»ºó¿ÉÒÔͨ¹ýÕâÖÖ°ì·¨À´Åжϵ±Ç°¶ÔÏóÊDz»ÊÇ block£º

BOOL FBObjectIsBlock(void *object) {  
Class blockClass = _BlockClass();

Class candidate = object_getClass((__bridge id)object);
return [candidate isSubclassOfClass:blockClass];
}

Block ÈçºÎ³ÖÓжÔÏó

ÔÚÕâһС½Ú£¬ÎÒÃǽ«ÌÖÂÛ block ÊÇ ÈçºÎ³ÖÓжÔÏó µÄ£¬ÎÒÃÇ»áͨ¹ý¶Ô FBRetainCycleDetector µÄÔ´´úÂë½øÐзÖÎö×îºó¾¡Á¿Ï꾡µØ»Ø´ðÕâÒ»ÎÊÌâ¡£

ÖØÐ»ص½ÎÄÕ¿ªÍ·Ìáµ½µÄ - allRetainedObjects ·½·¨£º

- (NSSet *)allRetainedObjects {
NSMutableArray *results = [[[super allRetainedObjects] allObjects] mutableCopy];

__attribute__((objc_precise_lifetime)) id anObject = self.object;

void *blockObjectReference = (__bridge void *)anObject;
NSArray *allRetainedReferences = FBGetBlockStrongReferences(blockObjectReference);

for (id object in allRetainedReferences) {
FBObjectiveCGraphElement *element = FBWrapObjectGraphElement(self, object, self.configuration);
if (element) {
[results addObject:element];
}
}

return [NSSet setWithArray:results];
}

 

ͨ¹ýº¯ÊýµÄ·ûºÅÎÒÃÇÒ²Äܹ»²Â²â³ö£¬ÉÏÊö·½·¨ÖÐͨ¹ý FBGetBlockStrongReferences »ñÈ¡ block ³ÖÓеÄËùÓÐÇ¿ÒýÓãº

NSArray *FBGetBlockStrongReferences(void *block) {  
if (!FBObjectIsBlock(block)) {
return nil;
}

NSMutableArray *results = [NSMutableArray new];

void **blockReference = block;
NSIndexSet *strongLayout = _GetBlockStrongLayout(block);
[strongLayout enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
void **reference = &blockReference[idx];

if (reference && (*reference)) {
id object = (id)(*reference);

if (object) {
[results addObject:object];
}
}
}];

return [results autorelease];
}

¶ø FBGetBlockStrongReferences ÊǶÔÁíÒ»¸ö˽Óк¯Êý _GetBlockStrongLayout µÄ·â×°£¬Ò²ÊÇʵÏÖ×îÓÐÒâ˼µÄ²¿·Ö¡£

¼¸¸ö±ØÒªµÄ¸ÅÄî

ÔÚ¾ßÌå½éÉÜ _GetBlockStrongLayout º¯ÊýµÄÔ´´úÂë֮ǰ£¬ÎÒÏ£ÍûÏÈ¶ÔÆäÔ­ÀíÓÐÒ»¸ö¼òµ¥µÄ½éÉÜ£¬±ãÓÚ¸÷λ¶ÁÕßµÄÀí½â£»ÔÚÕâÀïÓÐÈý¸ö¸ÅÄîÐèÒª½éÉÜ£¬Ê×ÏÈÊÇ block ³ÖÓеĶÔÏó¶¼´æÔÚµÄλÖá£

ÈçºÎ³ÖÓжÔÏó

ÔÚÎÄÕµÄÉÏÃæÔø¾­³öÏÖ¹ý block µÄ½á¹¹Ì壬²»ÖªµÀ¸÷λ¶ÁÕßÊÇ·ñ»¹ÓÐÓ¡Ïó£º

struct BlockLiteral {  
void *isa;
int flags;
int reserved;
void (*invoke)(void *, ...);
struct BlockDescriptor *descriptor;
// imported variables
};

ÔÚÿ¸ö block ½á¹¹ÌåµÄÏÂÃæ¾Í»á´æ·Åµ±Ç° block ³ÖÓеÄËùÓжÔÏó£¬ÎÞÂÛÇ¿Èõ¡£ÎÒÃÇ¿ÉÒÔ×öÒ»¸öСʵÑéÀ´ÑéÖ¤Õâ¸ö¹Ûµã£¬ÎÒÃÇÔÚ³ÌÐòÖÐÉùÃ÷ÕâÑùÒ»¸ö block£º

NSObject *firstObject = [NSObject new];  
__attribute__((objc_precise_lifetime)) NSObject *object = [NSObject new];
__weak NSObject *secondObject = object;
NSObject *thirdObject = [NSObject new];

__unused void (^block)() = ^{
__unused NSObject *first = firstObject;
__unused NSObject *second = secondObject;
__unused NSObject *third = thirdObject;
};

È»ºóÔÚ´úÂëÖдòÒ»¸ö¶Ïµã£º

ÉÏÃæ´úÂëÖÐ block ÓÉÓÚ±»±äÁ¿ÒýÓã¬Ö´ÐÐÁË _Block_copy £¬ËùÒÔÆäÀàÐÍΪ __NSMallocBlock__ £¬Ã»Óб»±äÁ¿ÒýÓÃµÄ block ¶¼ÊÇ __NSStackBlock__ ¡£

1.Ê×ÏÈ´òÓ¡ block ±äÁ¿µÄ´óС£¬ÒòΪ block ±äÁ¿ÆäʵֻÊÇÒ»¸öÖ¸Ïò½á¹¹ÌåµÄÖ¸Õ룬ËùÒÔ´óСΪ 8£¬¶ø½á¹¹ÌåµÄ´óСΪ 32£»

2.ÒÔ block µÄµØÖ·Îª»ùÖ·£¬Æ«ÒÆ 32£¬µÃµ½Ò»¸öÖ¸Õë

3.ʹÓà $3[0] $3[1] $3[2] ÒÀ´Î´òÓ¡µØÖ·Îª 0x1001023b0 0x1001023b8 0x1001023c0 µÄÄÚÈÝ£¬¿ÉÒÔ·¢ÏÖËüÃǾÍÊÇ block ²¶»ñµÄÈ«²¿ÒýÓã¬Ç°Á½¸öÊÇÇ¿ÒýÓã¬×îºóµÄÊÇÈõÒýÓÃ

Õâ¿ÉÒԵóöÒ»¸ö½áÂÛ£ºblock ½«Æä²¶»ñµÄÒýÓôæ·ÅÔڽṹÌåµÄÏÂÃæ£¬µ«ÊÇΪʲôÕâÀïµÄ˳Ðò²¢²»Êǰ´ÕÕÒýÓõÄ˳ÐòÄØ£¿½ÓÏÂÀ´Ôö¼Ó¼¸¸ö±äÁ¿£¬ÔÙ×öÁíÒ»´ÎʵÑ飺

ÔÚ´úÂëÖжà¼ÓÈëÁ˼¸¸ö¶ÔÏóÖ®ºó£¬block ¶Ô³ÖÓеĶÔÏóµÄ²¼¾ÖµÄ˳ÐòÒÀÈ»ÊÇ Ç¿ÒýÓÃÔÚǰ¡¢ÈõÒýÓÃÔÚºó £¬ÎÒÃDz»·Á×öÒ»¸ö¼ÙÉ裺 block »á½«Ç¿ÒýÓõĶÔÏóÅÅ·ÅÔÚÈõÒýÓöÔÏóµÄÇ°Ãæ ¡£µ«ÊÇÕâ¸ö¼ÙÉèÄܹ»°ïÖúÎÒÃÇÔÚ Ö»ÓÐ block µ«ÊÇûÓÐÉÏÏÂÎÄÐÅÏ¢µÄÇé¿öÏÂÇø·ÖÄÄЩÊÇÇ¿ÒýÓÃô£¿ÎÒ¾õµÃ²¢²»ÄÜ£¬ÒòΪÎÒÃÇûÓа취֪µÀËüÃÇÖ®¼äµÄ·Ö½çÏßµ½µ×ÔÚÄÄÀï¡£

dispose_helper

µÚ¶þ¸öÐèÒª½éÉܵÄÊÇ dispose_helper £¬ÕâÊÇ BlockDescriptor ½á¹¹ÌåÖеÄÒ»¸öÖ¸Õ룺

struct BlockDescriptor {  
unsigned long int reserved; // NULL
unsigned long int size;
// optional helper functions
void (*copy_helper)(void *dst, void *src); // IFF (1<<25)
void (*dispose_helper)(void *src); // IFF (1<<25)
const char *signature; // IFF (1<<30)
};

ÉÏÃæµÄ½á¹¹ÌåÖÐÓÐÁ½¸öº¯ÊýÖ¸Õ룬 copy_helper ÓÃÓÚ block µÄ¿½±´£¬ dispose_helper ÓÃÓÚ block µÄ dispose Ò²¾ÍÊÇ block ÔÚÎö¹¹µÄʱºò»áµ÷ÓÃÕâ¸öº¯ÊýÖ¸Õ룬Ïú»Ù×Ô¼º³ÖÓеĶÔÏ󣬶øÕâ¸öÔ­ÀíÒ²ÊÇÇø±ðÇ¿ÈõÒýÓõĹؼü£¬ÒòΪÔÚ dispose_helper»á¶ÔÇ¿ÒýÓ÷¢ËÍ release ÏûÏ¢£¬¶ÔÈõÒýÓò»»á×öÈκεĴ¦Àí¡£

FBBlockStrongRelationDetector

×îºó¾ÍÊÇÓÃÓÚ´Ó dispose_helper ½ÓÊÕÏûÏ¢µÄÀà FBBlockStrongRelationDetector ÁË£»ËüµÄʵÀýÔÚ½ÓÊÜ release ÏûϢʱ£¬²¢²»»áÕæÕýµÄÊÍ·Å£¬Ö»»á½«±ê¼Ç _strong Ϊ YES£º

- (oneway void)release {
_strong = YES;
}

- (oneway void)trueRelease {
[super release];
}

Ö»ÓÐÕæÕýÖ´ÐÐ trueRelease µÄʱºò²Å»áÏò¶ÔÏó·¢ËÍ release ÏûÏ¢¡£

ÒòΪÕâ¸öÎļþ¸²Ð´ÁË release ·½·¨£¬ËùÒÔÒªÔÚ·Ç ARC ϱàÒ룺

#if __has_feature(objc_arc)
#error This file must be compiled with MRR. Use -fno-objc-arc flag.
#endif

Èç¹û block ³ÖÓÐÁËÁíÒ»¸ö block ¶ÔÏó£¬ FBBlockStrongRelationDetector Ò²¿ÉÒÔ½«×ÔÉí fake ³ÉΪһ¸ö¼ÙµÄ block ·ÀÖ¹ÔÚ½ÓÊÕµ½¹ØÓÚ block ÊͷŵÄÏûϢʱ·¢Éú crash£º

struct _block_byref_block;  
@interface FBBlockStrongRelationDetector : NSObject {
// __block fakery
void *forwarding;
int flags; //refcount;
int size;
void (*byref_keep)(struct _block_byref_block *dst, struct _block_byref_block *src);
void (*byref_dispose)(struct _block_byref_block *);
void *captured[16];
}

¸ÃÀàµÄʵÀýÔÚ³õʼ»¯Ê±£¬»áÉèÖà forwarding ¡¢ byref_keep ºÍ byref_dispose £¬ºóÁ½¸ö·½·¨µÄʵÏÖ¶¼Êǿյģ¬Ö»ÊÇΪÁË·ÀÖ¹ crash£º

+ (id)alloc {
FBBlockStrongRelationDetector *obj = [super alloc];

// Setting up block fakery
obj->forwarding = obj;
obj->byref_keep = byref_keep_nop;
obj->byref_dispose = byref_dispose_nop;

return obj;
}

static void byref_keep_nop(struct _block_byref_block *dst, struct _block_byref_block *src) {}
static void byref_dispose_nop(struct _block_byref_block *param) {}

»ñÈ¡ block Ç¿ÒýÓõĶÔÏó

µ½ÏÖÔÚΪֹ£¬»ñÈ¡ block Ç¿ÒýÓöÔÏóËùÐèÒªµÄ֪ʶ¶¼½éÉÜÍêÁË£¬½ÓÏÂÀ´¿ÉÒÔ¶Ô˽Óз½·¨ _GetBlockStrongLayout ½øÐзÖÎöÁË£º

static NSIndexSet *_GetBlockStrongLayout(void *block) {  
struct BlockLiteral *blockLiteral = block;

if ((blockLiteral->flags & BLOCK_HAS_CTOR)
|| !(blockLiteral->flags & BLOCK_HAS_COPY_DISPOSE)) {
return nil;
}

...
}

1.Èç¹û block ÓÐ Cpp µÄ¹¹ÔìÆ÷/Îö¹¹Æ÷£¬ËµÃ÷Ëü ³ÖÓеĶÔÏóºÜÓпÉÄÜûÓа´ÕÕÖ¸Õë´óС¶ÔÆë £¬ÎÒÃǺÜÄѼì²âµ½ËùÓеĶÔÏó

2.Èç¹û block ûÓÐ dispose º¯Êý£¬ËµÃ÷ËüÎÞ·¨ retain ¶ÔÏó£¬Ò²¾ÍÊÇ˵ÎÒÃÇҲûÓа취²âÊÔÆäÇ¿ÒýÓÃÁËÄÄЩ¶ÔÏó

static NSIndexSet *_GetBlockStrongLayout(void *block) {  
...
void (*dispose_helper)(void *src) = blockLiteral->descriptor->dispose_helper;
const size_t ptrSize = sizeof(void *);
const size_t elements = (blockLiteral->descriptor->size + ptrSize - 1) / ptrSize;

void *obj[elements];
void *detectors[elements];

for (size_t i = 0; i < elements; ++i) {
FBBlockStrongRelationDetector *detector = [FBBlockStrongRelationDetector new];
obj[i] = detectors[i] = detector;
}

@autoreleasepool {
dispose_helper(obj);
}
...
}

1.´Ó BlockDescriptor È¡³ö dispose_helper ÒÔ¼° size £¨block ³ÖÓеÄËùÓжÔÏóµÄ´óС£©

2. ͨ¹ý (blockLiteral->descriptor->size + ptrSize - 1) / ptrSize ÏòÉÏÈ¡Õû£¬»ñÈ¡ block ³ÖÓеÄÖ¸ÕëµÄÊýÁ¿

3.³õʼ»¯Á½¸ö°üº¬ elements ¸ö FBBlockStrongRelationDetector ʵÀýµÄÊý×飬ÆäÖеÚÒ»¸öÊý×éÓÃÓÚ´«Èë dispose_helper £¬µÚ¶þ¸öÊý×éÓÃÓÚ¼ì²â _strong ÊÇ·ñ±»±ê¼ÇΪ YES

4.ÔÚ×Ô¶¯ÊͷųØÖÐÖ´ÐÐ dispose_helper(obj) £¬ÊÍ·Å block ³ÖÓеĶÔÏó

static NSIndexSet *_GetBlockStrongLayout(void *block) {  
...
NSMutableIndexSet *layout = [NSMutableIndexSet indexSet];

for (size_t i = 0; i < elements; ++i) {
FBBlockStrongRelationDetector *detector = (FBBlockStrongRelationDetector *)(detectors[i]);
if (detector.isStrong) {
[layout addIndex:i];
}

[detector trueRelease];
}

return layout;
}

ÒòΪ dispose_helper Ö»»áµ÷Óà release ·½·¨£¬µ«ÊÇÕâ²¢²»»áµ¼ÖÂÎÒÃÇµÄ FBBlockStrongRelationDetector ʵÀý±»Êͷŵô£¬·´¶ø»á±ê¼Ç _string ÊôÐÔ£¬ÔÚÕâÀïÎÒÃÇÖ»ÐèÒªÅжÏÕâ¸öÊôÐÔµÄÕæ¼Ù£¬½«¶ÔÓ¦Ë÷Òý¼ÓÈëÊý×飬×îºóÔÙµ÷Óà trueReleaseÕæÕýµÄÊͷŶÔÏó¡£

ÎÒÃÇ¿ÉÒÔÖ´ÐÐÏÂÃæµÄ´úÂ룬·ÖÎöÆä¹¤×÷¹ý³Ì£º

NSObject *firstObject = [NSObject new];  
__attribute__((objc_precise_lifetime)) NSObject *object = [NSObject new];
__weak NSObject *secondObject = object;
NSObject *thirdObject = [NSObject new];

__unused void (^block)() = ^{
__unused NSObject *first = firstObject;
__unused NSObject *second = secondObject;
__unused NSObject *third = thirdObject;
};

FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
[detector addCandidate:block];
[detector findRetainCycles];

ÔÚ dispose_helper µ÷ÓÃ֮ǰ£º

obj Êý×éÖеÄÿһ¸öλÖö¼´æ´¢ÁË FBBlockStrongRelationDetector µÄʵÀý£¬µ«ÊÇÔÚ dispose_helper µ÷ÓÃÖ®ºó£º

Ë÷ÒýΪ 4 ºÍ 5 ´¦µÄʵÀýÒѾ­±»Çå¿ÕÁË£¬ÕâÀï¶ÔÓ¦µÄ FBBlockStrongRelationDetector ʵÀýµÄ strong ÒѾ­±»±ê¼ÇΪ YES ¡¢¼ÓÈëµ½Êý×éÖв¢·µ»Ø£»×îºóÒ²¾Í»ñÈ¡ÁËËùÓÐÇ¿ÒýÓõÄË÷Òý£¬Í¬Ê±µÃµ½ÁË block Ç¿ÒýÓõĶÔÏó¡£

×ܽá

Æäʵ×ʼ±ÊÕß¶ÔÕâ¸ö dispose_helper ʵÏֵĻúÖÆ²¢²»ÊÇÌØ±ðµÄ¿Ï¶¨£¬Ö»ÊÇÓÐÒ»¸ö²Â²â£¬µ«ÊÇÔÚѯÎÊFBBlockStrongRelationDetector µÄ×÷ÕßÖ®ºó£¬²ÅÈ·¶¨dispose_helper ȷʵ»á¸ºÔðÏòËùÓв¶»ñµÄ±äÁ¿·¢ËÍ release ÏûÏ¢£¬Èç¹ûÓÐÐËȤ¿ÉÒÔ¿´Õâ¸öissue¡£Õⲿ·ÖµÄ´úÂëÆäʵ×ʼԴÓÚ mikeash ´óÉñµÄCircle£¬²»¹ý¶ÔÓÚËûÊÇÈçºÎ·¢ÏÖÕâÒ»µãµÄ£¬±ÊÕß²¢²»Çå³þ£¬Èç¹û¸÷λÓÐÏà¹ØµÄ×ÊÁÏ»òÕߺÏÀíµÄ½âÊÍ£¬¿ÉÒÔËæÊ±ÁªÏµÎÒ¡£

 

   
2209 ´Îä¯ÀÀ       29
 
Ïà¹ØÎÄÕÂ

ÊÖ»úÈí¼þ²âÊÔÓÃÀýÉè¼ÆÊµ¼ù
ÊÖ»ú¿Í»§¶ËUI²âÊÔ·ÖÎö
iPhoneÏûÏ¢ÍÆËÍ»úÖÆÊµÏÖÓë̽ÌÖ
AndroidÊÖ»ú¿ª·¢£¨Ò»£©
 
Ïà¹ØÎĵµ

Android_UI¹Ù·½Éè¼Æ½Ì³Ì
ÊÖ»ú¿ª·¢Æ½Ì¨½éÉÜ
androidÅÄÕÕ¼°ÉÏ´«¹¦ÄÜ
Android½²ÒåÖÇÄÜÊÖ»ú¿ª·¢
Ïà¹Ø¿Î³Ì

Android¸ß¼¶Òƶ¯Ó¦ÓóÌÐò
Androidϵͳ¿ª·¢
AndroidÓ¦Óÿª·¢
ÊÖ»úÈí¼þ²âÊÔ
×îл¼Æ»®
DeepSeekÔÚÈí¼þ²âÊÔÓ¦ÓÃʵ¼ù 4-12[ÔÚÏß]
DeepSeek´óÄ£ÐÍÓ¦Óÿª·¢Êµ¼ù 4-19[ÔÚÏß]
UAF¼Ü¹¹ÌåϵÓëʵ¼ù 4-11[±±¾©]
AIÖÇÄÜ»¯Èí¼þ²âÊÔ·½·¨Óëʵ¼ù 5-23[ÉϺ£]
»ùÓÚ UML ºÍEA½øÐзÖÎöÉè¼Æ 4-26[±±¾©]
ÒµÎñ¼Ü¹¹Éè¼ÆÓ뽨ģ 4-18[±±¾©]

androidÈË»ú½çÃæÖ¸ÄÏ
AndroidÊÖ»ú¿ª·¢£¨Ò»£©
AndroidÊÖ»ú¿ª·¢£¨¶þ£©
AndroidÊÖ»ú¿ª·¢£¨Èý£©
AndroidÊÖ»ú¿ª·¢£¨ËÄ£©
iPhoneÏûÏ¢ÍÆËÍ»úÖÆÊµÏÖ̽ÌÖ
ÊÖ»úÈí¼þ²âÊÔÓÃÀýÉè¼ÆÊµ¼ù
ÊÖ»ú¿Í»§¶ËUI²âÊÔ·ÖÎö
ÊÖ»úÈí¼þ×Ô¶¯»¯²âÊÔÑо¿±¨¸æ

Android¸ß¼¶Òƶ¯Ó¦ÓóÌÐò
AndroidÓ¦Óÿª·¢
Androidϵͳ¿ª·¢
ÊÖ»úÈí¼þ²âÊÔ
ǶÈëʽÈí¼þ²âÊÔ
AndroidÈí¡¢Ó²¡¢ÔÆÕûºÏ

ÁìÏÈIT¹«Ë¾ android¿ª·¢Æ½Ì¨×î¼Ñʵ¼ù
±±¾© Android¿ª·¢¼¼Êõ½ø½×
ijÐÂÄÜÔ´ÁìÓòÆóÒµ Android¿ª·¢¼¼Êõ
ijº½Ì칫˾ Android¡¢IOSÓ¦ÓÃÈí¼þ¿ª·¢
°¢¶û¿¨ÌØ LinuxÄÚºËÇý¶¯
°¬Ä¬Éú ǶÈëʽÈí¼þ¼Ü¹¹Éè¼Æ
Î÷ÃÅ×Ó Ç¶Èëʽ¼Ü¹¹Éè¼Æ