2015-10-09 3 views
1

Я пытаюсь создать подкласс NSTextFieldCell для использования с пользовательским NSTextField (с Swift). Однако мой код ломается при попытке копирования подкласса. Основной код у меня естьКопирование подкласса NSTextFieldCell в Swift вызывает сбой

class XYTextFieldCell: NSTextFieldCell { 
    var borderColor = NSColor.init(red: 0.5, green: 0.5, blue: 0.5, alpha: 1)   
    override init(imageCell image: NSImage?) { 
     super.init(imageCell: image) 
    } 

    override init(textCell aString: String) { 
     super.init(textCell: aString) 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
    } 

    deinit { 
     Swift.print("Deinit XYTextFieldCell: \(unsafeAddressOf(self))") 
    } 
} 

В AppDelegate (чтобы попытаться имитировать сбой в небольшом приложении), у меня есть

func applicationDidFinishLaunching(aNotification: NSNotification) { 
    let textFieldCell = XYTextFieldCell.init(textCell: "Test") 
    Swift.print("TextFieldCell: \(unsafeAddressOf(textFieldCell))") 
    print("textFieldCell.color: \(unsafeAddressOf(textFieldCell.borderColor))") 
    copyTextFieldCell(textFieldCell) 
} 

func copyTextFieldCell(textFieldCell: XYTextFieldCell) { 
    Swift.print("TextFieldCell (param): \(unsafeAddressOf(textFieldCell))") 
    let copy = textFieldCell.copy() as! XYTextFieldCell 
    Swift.print("TextFieldCell (copy): \(unsafeAddressOf(copy))") 
    print("copy.color: \(unsafeAddressOf(copy.borderColor))") 
} 

Приложение прекращает работу с

[NSColorSpaceColor release]: message sent to deallocated instance 0x600000075240 

Полный выходной is

TextFieldCell: 0x00006080000a61e0 
textFieldCell.color: 0x0000608000074840 
TextFieldCell (param): 0x00006080000a61e0 
TextFieldCell (copy): 0x00006080000a62a0 
copy.color: 0x0000608000074840 
Deinit XYTextFieldCell: 0x00006080000a62a0 
Deinit XYTextFieldCell: 0x00006080000a61e0 
2015-10-09 16:52:35.043 Test[86949:4746488] *** -[NSColorSpaceColor release]: message sent to deallocated instance 0x608000074840 

Он выглядит l ike borderColor не сохраняется правильно после копии (и удваивается). Затем я попытался добавить перегрузку копии, чтобы попытаться создать копию borderColor.

override func copyWithZone(zone: NSZone) -> AnyObject { 
     let myCopy = super.copyWithZone(zone) as! XYTextFieldCell 
     myCopy.borderColor = borderColor.copyWithZone(zone) as! NSColor 

     return myCopy 
    } 

Но, по-прежнему падает с той же ошибкой

TextFieldCell: 0x00006080000ab4c0 textFieldCell.color: 0x00006080000769c0  
TextFieldCell (param): 0x00006080000ab4c0 
TextFieldCell (copy): 0x00006080000ab520 
copy.color: 0x00006080000769c0 
Deinit XYTextFieldCell: 0x00006080000ab520 
Deinit XYTextFieldCell: 0x00006080000ab4c0 
2015-10-09 16:54:54.248 Test[87031:4749016] *** -[NSColorSpaceColor release]: message sent to deallocated instance 0x6080000769c0 

я могу избежать аварии, делая инициализации нового XYTextFieldCell внутри copyWithZone: (вместо вызова super.copyWithZone). Но это означало бы, что я должен вручную переназначить все свойства, определенные суперклассом, и на мою копию.

Есть ли способ сделать копию NSTextFieldCell правильно, чтобы он не удваивал мои свойства подкласса. Я замечаю это поведение при подклассе из NSButtonCell. Но, если я не наследую ни от (XYTextFieldCell - это корневой класс Swift), тогда он отлично работает. Спасибо

ответ

1

Похоже, я был пойман NSCopyObject(), как подробно here. Суть ссылки заключается в том, что подклассы NSCell используют NSCopyObject() для соответствия протоколу NSCopying - и NSCopyObject(), похоже, не корректно устанавливает учетные записи.

Решение, изложенное в Objective-C, и я не уверен, как его перевести на Swift (поскольку он включает прямой доступ к Objective-C ivars в методе copyWithZone:). Итак, мне пришлось реализовать базовый подкласс в объективе-c (и сделать копию в объективе-c). Я тогда мост, что к быстрому подклассу

RMTextFieldCell.h (в Objective-C)

#import <Cocoa/Cocoa.h> 

@interface RMTextFieldCell : NSTextFieldCell 

@property (nonatomic, strong) NSColor* borderColor; 

@end 

RMTextFieldCell.m (в Objective-C)

#import "RMTextFieldCell.h" 

@implementation RMTextFieldCell 

-(id) initTextCell:(NSString *)aString 
{ 
    self = [super initTextCell:aString]; 
    [self setup]; 

    return self; 
} 

-(id) initImageCell:(NSImage *)image 
{ 
    self = [super initImageCell:image]; 
    [self setup]; 

    return self; 
} 

-(id) initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super initWithCoder:aDecoder]; 
    [self setup]; 

    return self; 
} 

-(RMTextFieldCell*) copyWithZone:(NSZone*) zone 
{ 
    RMTextFieldCell* copy = [super copyWithZone:zone]; 
    copy->_borderColor = nil; 
    copy.borderColor = self.borderColor; 

    return copy; 
} 

-(void) setup 
{ 
    self.borderColor = [NSColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0]; 
} 

@end 

RMSwiftTextFieldCell.swift (в быстры)

import Cocoa 

class RMSwiftTextFieldCell: RMTextFieldCell { 


    override init(imageCell image: NSImage?) { 
     super.init(imageCell: image) 
    } 

    override init(textCell aString: String) { 
     super.init(textCell: aString) 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
    } 

    deinit { 
     Swift.print("Deinit RMTextFieldCell: \(unsafeAddressOf(self))") 
    } 
} 

Это немного запутанный, но, похоже, работает в моем первоначальном тестировании. Если у кого-то есть лучшее решение, я был бы признателен :) Спасибо

Редактировать: Похоже, мне даже не нужно реализовывать copyWithZone: в подклассе object-c.

 Смежные вопросы

  • Нет связанных вопросов^_^