Bug with NSString componentsSeparatedByString? - objective-c

I've been trying to read sections of a string into an array and encountered some problems. Though my task is more complicated, even a simple example case like the one below gives the same problem: the code compiles and runs but the the size of the strings array is always one and the only thing that's contained in strings[0] is "__NSArrayM".
NSString *string = #"John, Bob, Jane";
NSArray *strings = [string componentsSeparatedByString: #", "];
Thanks in advance for any ideas!

When you say "the size of the strings array", do you mean what you get from [strings count] or something else? Also, Objective-C doesn't let you access NSArray elements with the square bracket notation, so if you're literally calling strings[0] you're doing some pointer math on the Array object that you don't intend to be doing.

Related

Putting NSData into an NSArray

I have NSData objects storing data (non character / non-ascii). I'm trying to put it into an array without it being interpreted as characters or ascii. I know this question has been asked a few times before, but none of the solutions posted have worked for me in this situation. I'm trying to avoid using property lists, which is what most answers suggested. I already tried converting the NSData to an NSString, then storing the string in the array, but of course it is interpreted as characters after putting it in the string, regardless of the encoding I've used. For example, one of the NSData's contains the value 2c, and when I put it into a string it is interpreted as ,. Does anyone know how I can store the raw data, in its original state, in an NSArray? Maybe by storing the data in user defaults, then somehow storing the defaults in an array? I'm at a loss.
Here is some possibly relevant code:
NSData *receivedData = [bleDevice readData];
NSString *receivedDataString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
[dataArray insertObject:receivedDataString atIndex:0];
When I call:
[dataArray insertObject:receivedDataString atIndex:0];
It will store something like 2c ad a ,.
But, when I try and insert the raw data, like:
[dataArray insertObject:receivedData atIndex:0];
It will simply not store anything. There are no warnings, no errors. I'll NSLog the array and it is null.
[dataArray insertObject:receivedData atIndex:0]; most certainly will insert "receivedData" into "dataArray" (so long as both exist). "receivedData" can be any sort of NSObject -- need not be a string. If the array is "null" when you log it then the array itself never got created.
(It's important to remember that if an object pointer is nil then method calls on that pointer do not fail but rather silently return zero/nil, so "returns nil" strongly suggests the object never was created.)

Caesar Shift Encryption Objective C

I'm learning Objective C and iOS development. I'm trying to recreate some of the projects we did in my Java class (I know they're completely different) but I'm running into trouble in one of the projects. We were doing a caesar shift in a lab one day. A string manipulation lab. It was a really basic deal in Java... a for loop through the string and change each character. I can't seem to find any way to change individual characters in Objective C. I've looked through the NSMutableString documentation and NSString documentation and I know I can do a
[NSString stringByReplacingCharactersInRange:(NSRange *) withString:(NSString *)
but that doesn't really help because I don't know what I'm going to be replacing with. I need to find a way to grab a character at a specific index and change it. Any ideas?
Sounds like you are looking for the [NSString characterAtIndex:(NSUInteger)] method
E.g.
NSString *string = #"abcde";
NSString *character = [NSString stringWithFormat:#"%C",[string characterAtIndex: 0]];
NSLog(#"%#", character);
Result: a
Using this, and an NSMutableString, you can build the string you need.
Ussing appendString you can add to the end of an NSMutableString
Probably the best way to do this would be using a good old C-string, as that allows you to change the bytes without the overhead of reallocating a different string every time:
NSString *ceasarShift(NSString *input)
{
char *UTF8Str = strdup([input UTF8String]);
int length = [input length];
for (int i = 0; i < length; i++)
{
UTF8Str[i] = changeValueOf(UTF8Str[i]); // some code here to change the value
}
NSString *result = [NSString stringWithUTF8String:UTF8Str];
free(UTF8Str);
return result;
}
This reduces overhead, and although you have to free the data you allocated when you are done, it gives you the advantage of not relying on a high level API, improving performance drastically. (The difference between an array set and a dynamic method lookup is ~5 CPU cycles, which means a lot if you are doing any major sort of encryption)
Maybe also look into NSMutableData for this kind of task, instead of NSString, as the random \0 may per chance appear in the result string.

Pros and Cons of using [NSString stringWithString:#"some string"] versus #"some string"

I want to compare the following simple assignments:
...
#property(nonatomic,retain) UITextField *textField;
...
self.textField.text = #"some string";
self.textField.text = [NSString stringWithString:#"some string"];
self.textField.text = [NSString stringWithFormat:#"some string"];
Where textField is an UITextField and the text property a NSString. Of course all of them work. I know the difference of the last two when using parameters. But lets say we are only interested in this usage.
QUESTIONS:
For doing this kind of assignment, why shouldn't I always use the first one?
Comparing the last two, is there any difference for the compile- and/or runtime of these two? And why should I use stringWithString: at all if not?
Always try to do what feels natural. If you're assigning a constant string then do that, i.e. the first option. #"..." strings are very efficient constants that do not need to be memory managed, so use them if it makes sense.
NSLog(#"%p", #"XX");
NSLog(#"%p", #"XX");
NSLog(#"%p", #"XX");
Results in:
0xa2424
0xa2424
0xa2424
i.e. They are all the same object in memory.
NSLog(#"%p", [NSString stringWithString:#"XX"]);
NSLog(#"%p", #"XX");
NSLog(#"%p", [NSString stringWithString:#"XX"]);
Also results in:
0xa2424
0xa2424
0xa2424
As you can see from this there is no difference between the two objects, thus using -stringWithString: is just an extra message to send. Having said that, the overhead is usually not big enough to make a difference, so it shouldn't be a big deal either way. Personally I'd go with method one as there is no benefit of using method two, it's just extra code.
However,
NSLog(#"%p", [NSString stringWithFormat:#"XX"]);
NSLog(#"%p", [NSString stringWithFormat:#"XX"]);
NSLog(#"%p", [NSString stringWithFormat:#"XX"]);
Results in:
0x7f86730
0xf8479b0
0x8a4cdb0
As you can see, a new string is created each time as the sting you provide is just a format string that is used to process the following substitution variables, as you have none avoid stringWithFormat: unless you need it.
(Obviously all addresses are examples...)
For doing this kind of assignment, why shouldn't I always use the first one?
For that kind of assignment you would always use the first one, and never the last two.
why should I use stringWithString: at all if not?
Your intuition is correct. In most cases -stringWithString: is of dubious value. It's primarily meant for use with NSMutableString, which is a subclass of NSString.
For example:
NSMutableString* myString = [NSMutableString stringWithString:#"Foo"];
[myString appendString:#"Bar"];
You can also use it if you want to convert an NSMutableString to NSString, or otherwise ensure that you're dealing with an NSString instance. For example:
- (void):setMyString:(NSString*)newString
{
[_myString release];
_myString = [[NSString stringWithString:newString] retain];
}
That's one way to ensure that the _myString ivar is pointing to an NSString instance and not an NSMutableString instance. And the newString instance is only copied if necessary.
However, most developers would just use _myString = [newString copy]; in that case.
For doing this kind of assignment, why shouldn't I always use the first one?
You should always use the first one in the situation you describe. The second and third cases potentially copy the constant string, but the text property of UITextField is specified as copying the provided string anyway. There's no sense in making a copy of a constant string just so UITextField's -setText: can copy that copy.
Comparing the last two, is there any difference for the compile-
and/or runtime of these two? And why should I use stringWithString: at
all if not?
My understanding is that -stringWithFormat: will always create a new string, while -stringWithString: might not (probably doesn't) for a constant string. hypercrypt's results above are pretty telling in this respect; if you wanted to explore that more, you might try the same test with a mutable string.
I don't think it matters if you use the first or the second for strings.
I usually use the second one however.
In the case of the second and third, if you have another variable you would like to include in your string then you use the stringWithFormat one. Otherwise, use stringWithString.
int number = 5;
NSString *str = [NSString stringWithFormat:#"Number is: %i", number];
// Str is "Number is: 5"
Situation where you would use stringWithString:
NSString *myName = [NSString stringWithString:#"FN LN"];
// myName is "FN LN"
You would use the latter when you have no other variables to include in the string.
Also, this question has been answered countless times elsewhere.

How do you benefit from creating an NSArray in Objective-C?

Well, I've been learning Objective-C for a while now, and I don't get why creating an NSArray would be beneficial for you. It's just a collection of some stuff right? Why can't you just use them without making an NSArray. Or can you use the objects in it in the implementation of every one of your methods (even if it's a local ivar).
So, any help would be appreciated. Thanks guys!
You could make instance variables for every “item” you need:
NSString *str1;
NSString *str2;
NSString *str3;
…but that’s hard to work with, an array is simply more convenient. What would you do if you wanted to print all these strings?
NSLog(#"%#", str1);
NSLog(#"%#", str2);
NSLog(#"%#", str3);
Wouldn’t it be easier to loop over an array?
NSArray *strings = [NSArray arrayWithObjects:#"one", #"two", #"three", nil];
for (NSString *str in strings)
NSLog(#"%#", str);
How about if you have ten, twenty strings? And what if you don’t know how many strings you will need? What if you want to pass all these items to somebody else? Are you going to pass them one by one?
- (void) doSomethingWithString1: (NSString*) str1 andString2: (NSString*) str2…;
Or would you rather pass an array?
- (void) doSomethingWithMyStrings: (NSArray*) strings;
Very often, the NSArray you see is a front for an NSMutableArray working behind the scenes.
Billing it in the interface as an NSArray is just a way to ensure that it cannot be manipulated from without, which could have moderately disastrous consequences. (Thus, when asking for an NSArray from an object, you'll usually get a copy of the NSMutableArray used internally.)
Understanding why creating an NSMutableArray is beneficial is left as an exercise to the reader.
Different contexts.
When you use an NSString it's generally used for a single value. It's quite simple.
NSArray
If you want to loop through many keys/values, use an NSArray. It is not possible to loop through NSStrings because they don't have the order structer that NSArray's do.
Why use NSString
It would be silly to call myArray[0] and foo[0] every time you saved just a value. NSString is simpler than NSArray, since you can easily set a value on a GUI element (without having to call myArray[0])
Why use NSArray
It is more flexible than NSString because NSArray can hold multiple values, which may be needed in certain situations.
Weighing pros and cons
Pros (NSArray):
Can make your code cleaner (call myArray[1] and myArray[0] instead of mystring and foo)
Simplified memory management (easier to release one NSArray than many NSStrings)
Cons (NSArray):
Can make your code very complicated (was that on myArray[0] or 1?)
Might be difficult to know what type of data is in the array (if it's an NSString, it's always going to be a string, an array can hold many different types of data). You wouldn't use 50 tissues to dry yourself off from the shower but use a towel.
So it boils down to one thing. What context are you using?

Objective-C String-Replace

I want to replace multiple elements in my string in Objective-C.
In PHP you can do this:
str_replace(array("itemtoreplace", "anotheritemtoreplace", "yetanotheritemtoreplace"), "replacedValue", $string);
However in objective-c the only method I know is NSString replaceOccurancesOfString. Is there any efficient way to replace multiple strings?
This is my current solution (very inefficient and.. well... long)
NSString *newTitle = [[[itemTitleField.text stringByReplacingOccurrencesOfString:#"'" withString:#""] stringByReplacingOccurrencesOfString:#" " withString:#"'"] stringByReplacingOccurrencesOfString:#"^" withString:#""];
See what I mean?
Thanks,
Christian Stewart
If this is something you're regularly going to do in this program or another program, maybe make a method or conditional loop to pass the original string, and multi-dimensional array to hold the strings to find / replace. Probably not the most efficient, but something like this:
// Original String
NSString *originalString = #"My^ mother^ told me not to go' outside' to' play today. Why did I not listen to her?";
// Method Start
// MutableArray of String-pairs Arrays
NSMutableArray *arrayOfStringsToReplace = [NSMutableArray arrayWithObjects:
[NSArray arrayWithObjects:#"'",#"",nil],
[NSArray arrayWithObjects:#" ",#"'",nil],
[NSArray arrayWithObjects:#"^",#"",nil],
nil];
// For or while loop to Find and Replace strings
while ([arrayOfStringsToReplace count] >= 1) {
originalString = [originalString stringByReplacingOccurrencesOfString:[[arrayOfStringsToReplace objectAtIndex:0] objectAtIndex:0]
withString:[[arrayOfStringsToReplace objectAtIndex:0] objectAtIndex:1]];
[arrayOfStringsToReplace removeObjectAtIndex:0];
}
// Method End
Output:
2010-08-29 19:03:15.127 StackOverflow[1214:a0f] My'mother'told'me'not'to'go'outside'to'play'today.'Why'did'I'not'listen'to'her?
There is no more compact way to write this with the Cocoa frameworks. It may appear inefficient from a code standpoint, but in practice this sort of thing is probably not going to come up that often, and unless your input is extremely large and you're doing this incredibly frequently, you will not suffer for it. Consider writing these on three separate lines for readability versus chaining them like that.
You can always write your own function if you're doing something performance-critical that requires batch replace like this. It would even be a fun interview question. :)
Considered writing your own method? Tokenize the string and iterate through all of them replacing one by one, there really is no faster way than O(n) to replace words in a string.
Would be a single for loop at most.
Add the # to the start of the all the strings, as in
withString:#""
It's missing for a few.