Реализация NSCoding для NSKeyedArchiver и утечки памяти - PullRequest
3 голосов
/ 18 сентября 2010

У меня есть пользовательский объект, который я использую NSKeyedArchiver для преобразования в NSData, поэтому мой пользовательский объект реализует протокол NSCoding.Но когда я запускаю инструмент Instruments, он говорит мне, что в моем методе initWithCoder есть несколько утечек NSCFString объектов внутри initWithCoder.

Как правильно реализовать протокол 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

1 Ответ

1 голос
/ 10 мая 2018

Для реализации 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 - это в основном шаблон. Каждое свойство кодируется или декодируется как объект или тип, используя имя свойства в качестве ключа каждый раз. (Некоторые разработчики предпочитают определять константы NSString * для каждого ключевого пути, но это обычно не требуется).

...