Have trouble appending to an NSMutableString - objective-c

#interface MainView : UIView {
NSMutableString *mutableString;
}
#property (nonatomic, retain) NSMutableString *mutableString;
#end
#implementation MainView
#synthesize mutableString;
-(void) InitFunc {
self.mutableString=[[NSMutableString alloc] init];
}
-(void) AppendFunc:(*NString) alpha {
[self.mutableString stringByAppendingString:#"hello"];
NSLog(#"the appended String is: %#",self.mutableString);
int len=[self.mutableString length];
}
Hey Everyone,
i just want to know where I am doing wrong ??? . I tried this code but "mutableString" does not append any value (as value of "len"comes '0' and NSLog doesnt print any value for "mutableString"), though i ve searched on net for the solution, people implemented in the same fashion yet i dont know why my code isnt working.
Thanks in Advance
MGD

stringByAppendingString: creates new string. Use appendString: instead:
[mutableString appendString:#"hello"]

1) Your method names violate the naming conventions: use lower case letters to start with.
2) stringByAppendingString returns a new string as a result and doesn't modify your original. You should use [self.mutableString appendString:#"hello"]; instead.
3) Your init method is leaking. You should use mutableString = [[NSMutableString alloc] init]; and not use the dot syntax, as it will be retained otherwise (and a release would be missing).

Oh God, what a mess. The stringByAppendingString does not change the string, it creates and returns a new one:
// Sets str2 to “hello, world”, does not change str1.
NSMutableString *str1 = [NSMutableString stringWithString:#"hello, "];
NSString *str2 = [str1 stringByAppendingString:#"world"];
If you want to change the mutable string itself, use the appendString method:
// Does not return anything, changes str1 in place.
[str1 appendString:#"world"];
Also, this is a leak:
self.mutableString = [[NSMutableString alloc] init];
This is best written as:
mutableString = [[NSMutableString alloc] init];
…because using accessors in init and dealloc is not the best idea.

Related

Make variable names variables (Objective-c)

I'd like to do something like this:
.h
LocalRoom* zone1;
LocalRoom* zone2;
LocalRoom* zone3;
LocalRoom* zone4;
etc....
.m
NSString *number = 1;
NSString *variable = [NSString stringWithFormat: #"zone%#", number]
[[variable variableValue] broadcastChatMessage:redStringPrefix fromUser:#"server"];
emulating:
[zone1 broadcastChatMessage:redStringPrefix fromUser:#"server"];
How do I do this? Is it possible?
Given names like “zone1”, “zone2”, etc., I would make an array rather than a dictionary. Either way, these should not be separate variables.
#property(strong) NSMutableDictionary *zones;
-(id)init {
....
_zones = [[NSMutableDictionary alloc] init];
....
}
aZone = [_zones objectForKey: [NSString stringWithFormat:#"zone%d", someZoneNumber]];
... etc ...
You can do something similar using Key-Value Coding. You would write
[[self valueForKey:variable] broadcastChatMessage:redStringPrefix fromUser:#"server"];
rather than
[[variable variableValue] broadcastChatMessage:redStringPrefix fromUser:#"server"];
This would of course require that zone1, zone2, etc. are instance variables (or properties) on self.

Self assignment for NSString category

I want to self assign an adjusted nsstring via category.
The example is a trim function:
I do not want that way:
NSString *theTempString = [theExampleString xTrim];
// ... go on doing stuff with theTempString
I want it this way:
[theExampleString xTrim];
// ... go on doing stuff with theExmapleString
The category looks like this:
- (void)xTrim
{
self = [self stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
}
The error that an assignment outside init is not possible - I understand that.
But now I'm interested in it, of course I can write an custom init methode, but is there no way around it like the one above???
Greetings and thanks,
matthias
You don't need to create a new NSString, the method already does that for you:
- (NSString *)xTrim
{
return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}
NSString is immutable so you need to assign it:
yourString = [yourString xTrim];
You cannot do that in a category on NSString, because NSString manages immutable strings, which means that the string can not be changed after it has been created.
You could implement it as category on NSMutableString:
- (void)xTrim
{
NSString *trimmed = [self stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
[self setString:trimmed]; // replaces the characters of "self" with those of "trimmed".
}
And if your question is: Can I write a method xTrim such that
[theExampleString xTrim]
replaces the receiver theExampleString with a new instance: No, that is not possible.

Storing objects in an array in objective c

I'm trying to store 25 objects in an array
for (int iy=0; iy<5; iy++) {
for (int ix=0; ix<5; ix++) {
TerrainHex *myObject = [[TerrainHex alloc] initWithName:(#"grassHex instance 10000") width:mGameWidth height:mGameHeight indexX:ix indexY:iy];
myObject.myImage.y += 100;
[TerrainHexArray addObject:myObject];
[self addChild:(id)myObject.myImage];
}
}
NSLog(#"Terrain array: %u", [TerrainHexArray count]);
The log is coming back as zero though.
In the .h file I have
#property NSMutableArray *TerrainHexArray;
And in the .m file I have..
#synthesize TerrainHexArray;
I just tried what someone suggested below, which is..
NSMutableArray *TerrainHexArray = [[NSMutableArray] alloc] init];
But it's just giving me a warning saying expected identifier.
It's almost certain that TerrainHexArray does not exist when you're doing the addObject calls and the NSLog. You say you tried adding the alloc/init after someone suggested it, which indicates you don't understand object management in Objective-C.
I'd suggest you step back, find a book on Objective-C, and read at least the first few chapters (up through the discussion of alloc/init et al) before you attempt any more coding.
Incidentally, it's standard C++/Objective-C coding practice (except in Microsoft) to use identifiers with a leading lower case character for instance names, reserving leading caps for types/class names.
What is TerrainHexArray? It looks like a class name, not an instance of an array. If you create a mutable array, then you can add the items to the array.
NSMutableArray *hexArray = [[NSMutableArray] alloc] init];
for (int iy=0; iy<5; iy++) {
for (int ix=0; ix<5; ix++) {
TerrainHex *myObject = [[TerrainHex alloc] initWithName:(#"grassHex instance 10000") width:mGameWidth height:mGameHeight indexX:ix indexY:iy];
myObject.myImage.y += 100;
[hexArray addObject:myObject];
[self addChild:(id)myObject.myImage];
}
}
NSLog(#"Terrain array: %u", [hexArray count]);

Check strings for same characters in Objective-C

I have an array of strings, from which I would like to extract only those with unique character sets. (For example, "asdf" and "fdsa" would be considered redundant). This is the method I am currently using:
NSMutableArray *uniqueCharSets = [[NSMutableArray alloc] init];
NSMutableArray *uniqueStrings = [[NSMutableArray alloc] init];
for (NSString *_string in unique) {
NSCharacterSet *_charSet = [NSCharacterSet characterSetWithCharactersInString:_string];
if (![uniqueCharSets containsObject:_charSet]) {
[uniqueStrings addobject:_string];
[uniqueCharSets addObject:_charSet];
}
}
This seems to work, but it's very slow and resource-intensive. Can anyone think of a better way to do this?
Using an NSDictionary, map each string's lexicographically-sorted equivalent to an NSArray of input strings: (e.g. adfs => [afsd, asdf, ...])
Walk through the dictionary, printing out keys (or their values) which only have single-element array values
I just put together a quick example of how I would approach this, but it turns out that it is more, odd, than you first expect. For one, NSCharacterSet doesn't implement equality to check contents. It only uses the pointer value. Based on this your example will NOT work properly.
My approach is to use an NSSet to deal with the hashing of these for us.
#interface StringWrapper : NSObject
#property (nonatomic, copy) NSString *string;
#property (nonatomic, copy) NSData *charSetBitmap;
- (id)initWithString:(NSString*)aString;
#end
#implementation StringWrapper
#synthesize string, charSetBitmap;
- (id)initWithString:(NSString*)aString;
{
if ((self = [super init]))
{
self.string = aString;
}
return self;
}
- (void)setString:(NSString *)aString;
{
string = [aString copy];
self.charSetBitmap = [[NSCharacterSet characterSetWithCharactersInString:aString] bitmapRepresentation];
}
- (BOOL)isEqual:(id)object;
{
return [self.charSetBitmap isEqual:[object charSetBitmap]];
}
- (NSUInteger)hash;
{
return [self.charSetBitmap hash];
}
#end
int main (int argc, const char * argv[])
{
#autoreleasepool {
NSMutableSet *stringWrappers = [[NSMutableSet alloc] init];
NSArray *strings = [NSArray arrayWithObjects:#"abc",#"aaabcccc",#"awea",#"awer",#"abcde", #"ehra", #"QWEQ", #"werawe", nil];
for (NSString *str in strings)
[stringWrappers addObject:[[StringWrapper alloc] initWithString:str]];
NSArray *uniqueStrings = [stringWrappers valueForKey:#"string"];
NSLog(#"%#", uniqueStrings);
}
return 0;
}
The code is pretty straightforward. We create a container object to cache the results of the character set's bitmap representation. We use the bitmap representation because NSData implements isEqual: appropriately.
The only thing that come in my mind is not to use containsObject: since NSMutableArray is not ordered (in general), we can assume that containsObject simply iterates the array starting from the beginning until he finds the object. This means O(n) (n comparisons in the worst case).
A better solution may consists in keeping the array ordered and use a custom search method using a dichotomic approach. This way you'll have a O(log n) complexity.
Of course, you must take care of keeping your array ordered (much more efficient than add and reorder), so you should use insertObject:atIndex: method to insert the element properly.

Is it necessary to assign a string to a variable before comparing it to another?

I want to compare the value of an NSString to the string "Wrong". Here is my code:
NSString *wrongTxt = [[NSString alloc] initWithFormat:#"Wrong"];
if( [statusString isEqualToString:wrongTxt] ){
doSomething;
}
Do I really have to create an NSString for "Wrong"?
Also, can I compare the value of a UILabel's text to a string without assigning the label value to a string?
Do I really have to create an NSString for "Wrong"?
No, why not just do:
if([statusString isEqualToString:#"Wrong"]){
//doSomething;
}
Using #"" simply creates a string literal, which is a valid NSString.
Also, can I compare the value of a UILabel.text to a string without assigning the label value to a string?
Yes, you can do something like:
UILabel *label = ...;
if([someString isEqualToString:label.text]) {
// Do stuff here
}
if ([statusString isEqualToString:#"Wrong"]) {
// do something
}
Brian, also worth throwing in here - the others are of course correct that you don't need to declare a string variable. However, next time you want to declare a string you don't need to do the following:
NSString *myString = [[NSString alloc] initWithFormat:#"SomeText"];
Although the above does work, it provides a retained NSString variable which you will then need to explicitly release after you've finished using it.
Next time you want a string variable you can use the "#" symbol in a much more convenient way:
NSString *myString = #"SomeText";
This will be autoreleased when you've finished with it so you'll avoid memory leaks too...
Hope that helps!
You can also use the NSString class methods which will also create an autoreleased instance and have more options like string formatting:
NSString *myString = [NSString stringWithString:#"abc"];
NSString *myString = [NSString stringWithFormat:#"abc %d efg", 42];