检测 Obj-C 中的内存泄漏

Detect memory leaks in Obj-C

我有一段代码是用Objective-C写的,当我运行它的时候,它会导致内存泄漏。我找不到它出现在哪里。

@interface AddressCard : NSObject
@property (nonatomic,copy) NSString *name;
@property (nonatomic,copy) NSString *email;
-(void) print;
-(id)initWithName:(NSString*)name email: (NSString*)_email;
-(NSComparisonResult) compareNames:(id)element;
@end
@implementation AddressCard
@synthesize name = _name, email = _email;

-(id)initWithName:(NSString*)name email: (NSString*)mail{
    if (self = [super init]){
        self.name = name;
        self.email = mail;
    }
    return (self);
}

-(BOOL) isEqual:(AddressCard*)other {
    if ([self.name isEqualToString:other.name] == YES &&
        [self.email isEqualToString:other.email] == YES) {
        return (YES);
    }
    return (NO);
}
-(NSComparisonResult) compareNames:(id)element{
    return [self.name compare:[element name]];
}
-(void) dealloc {
    NSLog(@"Delete card %@ %@", [self name], [self email]);
}
@end
@interface AddressBook : NSObject{
    NSString *name;
    NSMutableArray *cards;
}
-(id) initWithName:(NSString*)newName;

-(void) addCard:(AddressCard*) newCard;
-(void) removeCard:(AddressCard*)cardToDelete;    
-(AddressCard*)lookUp:(NSString*) searchName;
-(void) test;
@end
@implementation AddressBook
-(id) initWithName:(NSString*)newName{
    if (self = [super init]) {
        name = [NSString stringWithString:newName];
        cards = [[NSMutableArray alloc]init];
    }
    return (self);
}
-(void) addCard:(AddressCard*) newCard{
    [cards addObject:newCard];
}     
-(AddressCard*)lookUp:(NSString*) searchName {
    for (AddressCard *card in cards) {
        if ([[card name] caseInsensitiveCompare:searchName] == NSOrderedSame) {
            return card;
        }
    }
    return (nil);
}

-(void) removeCard:(AddressCard*)cardToDelete{
    [cards removeObjectIdenticalTo:cardToDelete];
}

-(void) sort{
    [cards sortUsingSelector:@selector(compareNames:)];
}

-(void)dealloc {
    NSLog(@"deleting addressBook");
    //cards = nil;
}

-(void) test{ 
    for (AddressCard *card in cards) {
        NSLog(@"ref count %ld for %@", CFGetRetainCount((__bridge CFTypeRef)card), [card name]);
    }
}
@end

测试代码:

AddressBook *book = [[AddressBook alloc]initWithName:@"my book"];

        [book addCard: [[AddressCard alloc] initWithName:@"Chandler Rids" email:@"Chandler.R@gmail.com"]];
        [book addCard: [[AddressCard alloc] initWithName:@"Bob Dilan" email:@"bob.dilan@gmail.com"]];
        [book addCard: [[AddressCard alloc] initWithName:@"Frank Daragon" email:@"frank.daragon@gmail.com"]];
        NSLog(@"counting ref for items _1: ");
        [book test];
        __weak AddressCard *forDeleteCard = [book lookUp:@"Frank Daragon"];
        NSLog(@"Removing from addres book:");
        [book removeCard:forDeleteCard];
        NSLog(@"testing:");
        [book test];
        NSLog(@"---- count %ld for %@", CFGetRetainCount((__bridge CFTypeRef)forDeleteCard), [forDeleteCard name]);
        forDeleteCard = nil;
        book = nil;            
        NSLog(@"after deleting");

所以当我在书中查找卡片时,它 return 数组中该对象的引用,并且它的引用计数设置为 2,即使目标设置为 __weak 引用;而从书中删除的对象,它删除了#after deleting# 消息。 output

尝试在 Xcode 中使用 Memory Graph 调试器,它会准确显示是什么对象引用导致了这个问题。