【问题标题】:Implementing NSCoding for NSKeyedArchiver and memory leaks为 NSKeyedArchiver 和内存泄漏实现 NSCoding
【发布时间】:2011-04-14 03:25:56
【问题描述】:

我有一个自定义对象,我正在使用 NSKeyedArchiver 转换为 NSData,因此我的自定义对象实现了 NSCoding 协议。但是当我运行 Instruments 工具时,它告诉我 initWithCoder 方法在 initWithCoder 中有许多泄露的 NSCFString 对象。

实现 NSCoding 协议的正确方法是什么?

我的班级:

@interface EventProfile : NSObject <NSCoding>
    NSString *eventTitle;   
    NSString *groupName;                                
@end
@implementation EventProfile

// NSCoding methods
-(id) initWithCoder:(NSCoder *)decoder
{
    if (self = [super init])
    {
        eventTitle = [[decoder decodeObjectForKey:@"eventTitle"] retain];
        groupName = [[decoder decodeObjectForKey:@"groupName"] retain];
    }

    return self;
}
-(void) encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeObject:self.eventTitle forKey:@"eventTitle"];
    [encoder encodeObject:self.groupName forKey:@"groupName"];  
}
// Memory management
- (void)dealloc
{           
    [eventTitle release];
    [groupName release];

    [super dealloc];
}    

@end

【问题讨论】:

  • eventTitlegroupName 属性的定义是什么?如果他们是copy,我觉得一切正常。但是如果他们不小心assign 你可能会遇到问题。您是否还可以在initWithCoder: 方法中使用self.eventTitleself.groupName 测试运行代码?除此之外,泄漏可能是在使用 EventTitle 类的地方在不同的地方。
  • 是的,您的界面没有显示任何属性定义,但您在 encodeWithCoder: 中使用了 self.eventTitleself.groupName ??

标签: iphone memory-leaks


【解决方案1】:

要实现 encodeWithCoder:您应该检查对象的所有基本属性并使用 NSCoder 上的各种方法对它们进行编码。对于对象属性,只需使用 encodeObject:forKey:。键可以只是一个描述被编码属性的短字符串:

class Book: NSObject, NSCoding {
var title: String
var author: String
var pageCount: Int
var categories: [String]
var available: Bool

// Memberwise initializer
init(title: String, author: String, pageCount: Int, categories: [String], available: Bool) {
    self.title = title
    self.author = author
    self.pageCount = pageCount
    self.categories = categories
    self.available = available
}

// MARK: NSCoding

required convenience init?(coder decoder: NSCoder) {
    guard let title = decoder.decodeObjectForKey("title") as? String,
        let author = decoder.decodeObjectForKey("author") as? String,
        let categories = decoder.decodeObjectForKey("categories") as? [String]
        else { return nil }

    self.init(
        title: title,
        author: author,
        pageCount: decoder.decodeIntegerForKey("pageCount"),
        categories: categories,
        available: decoder.decodeBoolForKey("available")
    )
}

func encodeWithCoder(coder: NSCoder) {
    coder.encodeObject(self.title, forKey: "title")
    coder.encodeObject(self.author, forKey: "author")
    coder.encodeInt(Int32(self.pageCount), forKey: "pageCount")
    coder.encodeObject(self.categories, forKey: "categories")
    coder.encodeBool(self.available, forKey: "available")
}

}

如您所见,NSCoding 主要是样板文件。每个属性都被编码或解码为对象或类型,每次使用属性的名称作为键。 (一些开发者喜欢为每个 keypath 定义 NSString * 常量,但这通常是不必要的)。

【讨论】:

    猜你喜欢
    • 2016-08-08
    • 2011-07-03
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    • 1970-01-01
    • 2021-08-21
    • 2012-02-12
    • 1970-01-01
    相关资源
    最近更新 更多