It looks to me like sending setString: to a NSMutableString that hasn't had init called on it yet does not call init on it's own. For example:
NSMutableString *string; // Declare, but do not init yet
[string setString:@"foo"];
NSLog (@"%@",string); // Prints "(null)"
I'd like to overwrite this behavior, so that essentially
- (void) setString:(NSString *)aString
{
if (!self)
{
self = [self initWithString:aString];
}
else
{
[super setString:aString];
}
}
I could do so with a subclass, but I would have to go through my project and replace all my NSMutableStrings with my subclass, which is a pain. I was looking at the Apple Docs and it looks like what I want to do is create a Category for NSMutableString. I haven't used categories before, so I got a couple questions:
First, it looks like categories only allow me to add new methods, it doesn't allow me to overwrite existing methods. I suppose it is easy enough to just create a setStringWithInit: method that does what I want, so this first issue isn't really an issue after all (although I still have to do a find-replace through my project for setString, but oh well).
Second, and more importantly, how do I check if the sender of my new method is nil? If setString: returned something other than void, I think I could get it to work, but that's not the case here. How do I get the if (!self) check from my code above to work with a category?
Or are categories not the way to go for this kind of thing, and I'd just be better off sub-classing after all?
EDIT:
So the strings I'm using this on will actually be @propertys of a custom NSObject subclass. In my code, I'll actually be calling [myObject.someProperty setString:@"foo"];, and the debugger is showing me that someProperty is nil when I try to do this. Also, in other parts of my app I'm checking if (!myObject.someProperty) to see if that property has been used yet, so I don't want to just automatically self.someProperty = [[NSMutableString alloc] init]; in the init method of myObject's class.
Although now that I think about it, I think I can get away with replacing if (!myObject.someProperty) with if ([myObject.someProperty length] == 0), which would allow me to go through and alloc-init things right away. But if I'm initializing everything right away, that will create some memory space for it, correct? It's probably negligible though. Hm, perhaps this is what I should be doing instead.
macros FTW!
When I try to assign a value with this:
NSMutableString, or if Y isn't anNSStringorNSMutableStringYisnil, but I expect it will cause a crash, which is what I want.Drawbacks:
setString()instead of the stocksetString:setValue:forKey:, which I use extensively - one step at a time I guess) - a one size fits all solution would have been nice - maybe a topic for another question.Whatever I pass in has to be a
NSStringbefore I pass it, I cannot convert it to a string in line - but at least I get a build error if I try to do so, so it isn't up to me to remember to do so (still adds clutter though)NSMutableString *X;int y = 0;setString(X, [NSString stringWithFormat:@"%d",y]) // <--- Doesn't workNSString *Y = [NSStirng stringWithFormat:@"%d",y];setString(X,Y) // <--- Does work