繁体   English   中英

显然我不知道如何写一个二传手

[英]Apparently I don't know how to write a setter

我有一个很好的对象,描述了一个相对较大的数据集。 我决定在对象中实现一些辅助功能。

基本上,我不是使用NSString的标准setter,而是定义自己的setter并同时设置另一个对象。

例如:

-(void) setNumber:(NSString *)number_in
{
    number = [number_in copy];
    title = @"Invoice ";
    title = [title stringByAppendingString:number];
}

我知道我需要“标题”作为某种格式的财产。 标题是基于数字的,所以我创建了一个setter来一键设置数字和标题。 (标题有默认的合成setter ......我没有在其他地方定义它)

出于某种原因,我将消息发送到解除分配的实例错误。 如果我删除这个setter,代码工作正常。

我的属性定义在这里:

@property (nonatomic, copy) NSString *number;
@property (nonatomic, copy) NSString *title;

我试过保留,但没有用。 我设置malloc堆栈日志并记录下来:

Alloc: Block address: 0x06054520 length: 32
Stack - pthread: 0xa003f540 number of frames: 30
    0: 0x903ba1dc in malloc_zone_malloc
    1: 0x102b80d in _CFRuntimeCreateInstance
    2: 0x102d745 in __CFStringCreateImmutableFunnel3
    3: 0x10824dd in _CFStringCreateWithBytesNoCopy
    4: 0xae222e in -[NSPlaceholderString initWithCStringNoCopy:length:freeWhenDone:]
    5: 0xaf9e8e in _NSNewStringByAppendingStrings
    6: 0xaf9a76 in -[NSString stringByAppendingString:]
    7: 0x112ba in -[Invoice setNumber:] at Invoice.m:25
    8: 0x11901 in -[Invoice copyWithZone:] at Invoice.m:47
    9: 0x107c7ca in -[NSObject(NSObject) copy]
   10: 0x1117632 in -[NSArray initWithArray:range:copyItems:]
   11: 0x107f833 in -[NSArray initWithArray:copyItems:]
   12: 0x5595 in -[InvoicesTableViewController wrapper:didRetrieveData:] at InvoicesTableViewController.m:96
   13: 0x4037 in -[Wrapper connectionDidFinishLoading:] at Wrapper.m:288
   14: 0xb17172 in -[NSURLConnection(NSURLConnectionReallyInternal) sendDidFinishLoading]
   15: 0xb170cb in _NSURLConnectionDidFinishLoading
   16: 0x18ca606 in _ZN19URLConnectionClient23_clientDidFinishLoadingEPNS_26ClientConnectionEventQueueE
   17: 0x1995821 in _ZN19URLConnectionClient26ClientConnectionEventQueue33processAllEventsAndConsumePayloadEP20XConnectionEventInfoI12XClientEvent18XClientEventParamsEl
   18: 0x18c0e3c in _ZN19URLConnectionClient13processEventsEv
   19: 0x18c0cb7 in _ZN17MultiplexerSource7performEv
   20: 0x10fd01f in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
   21: 0x105b28b in __CFRunLoopDoSources0
   22: 0x105a786 in __CFRunLoopRun
   23: 0x105a240 in CFRunLoopRunSpecific
   24: 0x105a161 in CFRunLoopRunInMode
   25: 0x1c29268 in GSEventRunModal
   26: 0x1c2932d in GSEventRun
   27: 0x39542e in UIApplicationMain
   28: 0x2199 in main at main.m:14
   29: 0x2115 in start

最后,我不断收到此错误:

-[CFString release]: message sent to deallocated instance 0x4b5aee0

提前一百万感谢:)

使用self.title调用合成的setter以及释放number的旧值。

- (void)setNumber:(NSString *)number_in
{
    [number release];
    number = [number_in copy];
    self.title = [NSString stringWithFormat:@"Invoice %@", number];
}

title正在自动释放, number在程序中泄露。 要编写一个完整的setter,首先应复制传入的对象,然后执行发布。

-(void) setNumber:(NSString *)number_in {
    if (number == number_in) {
        return;
    }

    NSString *oldValue = number;
    number = [number_in copy];
    [oldValue release];

    self.title = [title stringByAppendingString:number];
}

先复制然后释放的原因是因为在不可变对象上调用copy可能会返回相同的对象而不是创建新副本。 因此,如果使用相同的对象调用setNumber两次,并且number首先被释放,则它变为无效,然后在该无效对象上调用copy会导致问题。

if检查是一个优化步骤,如果需要,可以删除。

另外,您可能想要查看有关编写自定义setter的文章

正如@tia和@Mark发布的那样,如果title总是依赖于number的值,那么title应该是readonly属性。 修改后的setNumber可能看起来像,

- (void) setNumber:(NSString *)number_in {
    if (number == number_in) {
        return;
    }

    NSString *oldNumber = number;
    number = [number_in copy];
    [oldNumber release];

    NSString *oldTitle = title;
    title = [title stringByAppendingString:number];
    [oldTitle release];
}

传递nil number_in时可能需要进行额外的检查,因为当nil传递给stringByAppendingString ,会引发NSInvalidArgumentException 所以这里有这个检查器的最终版本,

- (void) setNumber:(NSString *)number_in {
    if (number == number_in) {
        return;
    }

    NSString *oldNumber = number;
    number = [number_in copy];
    [oldNumber release];

    if (number) {
        NSString *oldTitle = title;
        title = [title stringByAppendingString:number];
        [oldTitle release];
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM