This makes no sense to me. Maybe someone here can explain why this happens.
I've got an NSMutableString that I alloc at the top of my iPhone app, then append to later in the process. It results in a SIGABRT, which doesn't add up to me. Here's the code:
Header File (simplified):
开发者_Python百科@interface MyAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
NSMutableString *locationErrorMessage;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, copy) NSMutableString *locationErrorMessage;
@end
And the relevant parts of the Main:
@implementation MyAppDelegate
@synthesize window;
@synthesize locationErrorMessage;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
self.locationErrorMessage = [[NSMutableString alloc] init];
}
- (void)anotherFunction {
[self.locationErrorMessage appendString: @"Blah Blah Blah"];
}
This all seems simple enough. What am I missing?
I would call this a bug in how property setters are generated, but the answer is pretty simple:
You declared the property as (nonatomic, copy)
. This means that whenever the locationErrorMessage
property is set, it's going to invoke copy
on the new value and use that copy as the property value.
Unfortunately, invoking copy
on an NSMutableString
does not result in an NSMutableString
, it results in an NSString
(which cannot be mutated using something like appendString:
).
So the simple fix would be to change the property declaration from copy
to retain
.
(I would say that the bug would be: If you declare a property for a mutable object as copy
, then the copy setter should actually use mutableCopy
and not copy
) => rdar://8416047
Your property is copying the passed in string. A copy always is immutable, so you’re trying to send appendString:
to an immutable NSString
. Declare your property as retain
and it will work or write a custom setter that copies the string using mutableCopy
.
You also have a memory leak, you should use [NSMutableString string]
instead of the alloc-init
sequence.
Btw, you have a leak there,
self.locationErrorMessage = [[NSMutableString alloc] init];
you're copying the value, but you never release the actual first allocated NSMutableString.
精彩评论