显然我不知道如何编写 setter
我有一个很好的对象,它描述了一个相对较大的数据集。我决定在对象中实现一些辅助功能。
基本上,我没有使用 NSString 的标准 setter,而是定义自己的 setter 并同时设置另一个对象。
例如:
-(void) setNumber:(NSString *)number_in
{
number = [number_in copy];
title = @"Invoice ";
title = [title stringByAppendingString:number];
}
我知道我需要“标题”作为某种格式的属性。标题是基于数字的,所以我创建了一个设置器来一拳设置数字和标题。 (标题具有默认的合成设置器...我没有在其他地方定义它)
出于某种原因,我收到发送到已释放实例错误的消息。如果我删除这个设置器,代码就可以正常工作。
我的属性定义在这里:
@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
提前感谢一百万:)
I have a nice object that describes a relatively large data set. I decided to implement some helper functionality in the object.
Basically, instead of using the standard setter for a NSString, I define my own setter and set another object at the same time.
For example:
-(void) setNumber:(NSString *)number_in
{
number = [number_in copy];
title = @"Invoice ";
title = [title stringByAppendingString:number];
}
I know I will need "title" as a property in a certain format. Title is based on the number, so I created a setter to set number and title in one punch. (title has the default synthesized setter...I don't define it elsewhere)
For some reason, I'm getting the message sent to deallocated instance error. If I delete this setter, the code works fine.
My property definition is here:
@property (nonatomic, copy) NSString *number;
@property (nonatomic, copy) NSString *title;
I've tried retaining, to no avail. I setup malloc stack logging and logged this:
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
In the end, I keep getting this error:
-[CFString release]: message sent to deallocated instance 0x4b5aee0
Thanks a million in advance :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用
self.title
调用合成的 setter 并释放number
的旧值。Use
self.title
to invoke your synthesized setter as well as release the old value fornumber
.title
正在自动释放,number
正在程序中泄漏。要编写完整的 setter,您应该首先复制传入的对象,然后进行释放。先复制然后释放的原因是因为在不可变对象上调用copy可能会返回相同的对象而不是创建新的副本。因此,如果使用同一个对象调用
setNumber
两次,并且number
首先被释放,则它会变得无效,然后在该无效对象上调用copy
可能会导致问题。if
检查是一个优化步骤,如果需要,您可以删除它。另外,您可能还想查看这篇文章 关于编写自定义设置器。
正如 @tia 和 @Mark 所发布的,如果 title 始终依赖于 number 的值,那么 title 应该是一个
readonly
属性。修改后的 setNumber 可能看起来像这样,当传递
nil
number_in 时,可能需要进行额外的检查,就像当将nil
传递给 < code>stringByAppendingString,会引发NSInvalidArgumentException
。这是带有该检查的 setter 的最终版本,title
is getting autoreleased andnumber
is leaking in the program. To write a thorough setter, you should first copy the passed in object, and then do a release.The reason for copying first and then releasing is because calling
copy
on an immutable object may return the same object back instead of creating a new copy. So ifsetNumber
is called twice with the same object, andnumber
was released first, it becomes invalid, then callingcopy
on that invalid object next could cause issues.The
if
check is an optimization step, which you could remove if you wanted.Also, you may want to checkout this article on writing custom setters.
As @tia and @Mark have posted, if title is always dependent on the value of number, then title should be a
readonly
property. The modifiedsetNumber
may then look like,Additional checks may be needed for when a
nil
number_in is passed, as when anil
is passed tostringByAppendingString
, aNSInvalidArgumentException
is raised. So here goes the final version of this setter with that check,