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.)
Related
First off, I'm not exactly sure what is happening or if I fully understand it enough to describe the issue so I'll try my best.
I'm encoding a NSData object that contains json and one of the objects contains a degree symbol. We believe this what is causing the issue and would like to remove it before encoding since the problem occurs during encoding.
I have plenty of options out there for removing certain characters from strings but none from doing it from the NSData object itself. Wondering if this is even possible or if its an issue with how I'm already encoding it.
This is how the NSData object is being encoded and turned back into a NSData object to serialize it to json. Right now I'm not trying to remove the degree symbol, using Latin 1 because another character I want to use but do not need it, this probably isn't the best way to do but it works for majority of other data objects that pass through it just not this one so this needs to change.
NSString* stringISOLatin1 = [NSString stringWithCString:data.bytes encoding:NSISOLatin1StringEncoding];
NSData* dataUTF8 = [stringISOLatin1 dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO];
The results are a little weird, most of the time it works fine, even including the degree symbol in the text when displayed on screen. Other times after encoding the string comes back messed up at the end which makes it unable to be serialized.
Any help would be appreciated even if it just leads to a better explanation of what is happen. Thanks
The problem is likely that you are using NSString:stringWithCString:encoding: to convert your data object. This function requires the data to be null terminated. NSData objects do not have to be NULL terminated because they have an explicit length. If the NULL character is missing it will continue to read whatever there happens to be after the string, giving you either garbage at the end or possibly crash because of memory violation.
Instead try using this:
NSString *stringISOLatin1 = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
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.
I need to use a bunch of string variables throughout my program. I reassign some of them quite often, while others are stuck with the same value during execution.
What's the best practice here?
In the first case, the variables should be NSMutableString and I should cast them to NSString (using the copy method) whenever they need to be arguments of functions that require NSString objects. Is that right?
When I reassign them to other constant values, I shouldn't have to dispose the previous content, right?
As for NSString objects, if I need to assign a new value to them, I guess I should deallocate them, allocate them again, and then assign the new value. Is that correct?
Unless you're actually modifying a string, you shouldn't use NSMutableString. You're reassigning the whole string to a new value, so stay with a regular NSString. Use the autoreleased versions, because that'll be more efficient than alloc/init/release all the time. You could also just reassign your strings to constants if you know what they'll be assigned to.
In the first case, the variables should be NSMutableString and I should cast them to NSString (using the copy method) whenever they need to be arguments of functions that require NSString objects. Is that right?
Well, you could do it that way, but it would be really inefficient. Remember inheritance—an NSMutableString is an NSString, just with some new stuff tacked on. A simple cast will do the trick:
NSString *string = (NSString *)aMutableString;
Even better though, you don't even have to do that. Because of inheritance, you can directly pass in a mutable string wherever a regular string is required, no casting required. That's the beauty of inheritance.
When I reassign them to other constant values, I shouldn't have to dispose the previous content, right
For neither mutable or immutable strings. Old values are simply overwritten in memory—nothing to dispose of there. As far as the memory management goes, it's really not efficient to literally be creating new strings all the time. Just reassign them. You will never need to alloc/init one string more than once, and that single init should be balanced by a single release.
Addendum: When Should You Use Mutable?
A mutable string should be used when you are physically changing the value of the existing string, without completely discarding the old value. Examples might include adding a character to the beginning or the end, or changing a character in the middle. With a mutable string, you can do this "in place"—you'll just modify the existing string. By contrast, an immutable string, once its value is set, cannot change that value. NSString has methods such as stringByAppendingString:, which does add a string to an existing one—but it returns a new string. Behind the scenes, NSString has copied your old string to a new (larger) memory location, added the argument, and returned the new string. That copying is a lot less efficient (relatively speaking, or if you have to do it a lot).
Of course, there's nothing stopping you from physically assigning one string to another. Old values will be overwritten. Most NSStrings, including the #"String Constants", are autoreleased. If you are creating a new string and you decide to alloc/init, you can then assign it to another value without consequence:
myString = anotherString;
myString = myTextField.text;
You can do this with both mutable and immutable strings. The main takeaway is that you should only use mutable when your changing the string itself. But you can change the variable with both mutable and immutable strings without compiler or runtime issues (short of memory management, but most of it is autoreleased anyway).
As for NSString objects, if I need to
assign a new value to them, I guess I
should deallocate them, allocate them
again, and then assign the new value.
Is that correct?
You don't deallocate NSString if you didn't allocated it before, like here:
NSString *string = [NSString stringWithFormat:#"Hello"];
You only need to deallocate it when you call alloc:
NSString *string = [[NSString alloc] initWithString:#"Hello"];
[string release];
The only difference between NSMutableString* and NSString* is that mutable string can be changed.
You don't have to cast anything, since NSMutableString is a subclass of NSString, nor take different memory measures ( so you are right * ).
If you need a modifiable version of a string you just do
NSMutableString* myMutableString = [NSMutableString stringWithString:myString];
You should not 'copy' anything.
Note that if you call :
NSString* myString = myMutableString;
myString is still a mutable String.
So if for any reason (security...) you relly need unmutable strings, you have to call
NSString* myString = [NSString stringWithString:myMutableString];
* you are right, but you could also call [replaceCharactersInRange:withString:] on the mutable string. if there is enough space from previous allocation, then it may be faster, since there is no destruction and new allocation to do.
( Added later : forgot the setString: method )
I'm writing an iPhone application that uses a lot of editable text fields. I've been learning a lot about UITextFields and NSStrings by reading various references online, but there are some details that still elude me. When a user puts in an incorrect value for one of my text fields, I throw up an error message and put the text field back to the way it was before their input. For empty text fields, I've been doing this:
theTextField.text = #"";
Is this the best way to do this? I just came up with the idea myself, I don't know if there are any problems with it (other than the fact that it seems to work just fine so far).
Also, does #"" have the same value as a "nil" string? In other words, if I set a string to #"" and then call this:
if (myString) {...}
will the statement return true or false?
One last thing. When an NSString is initialized using this:
NSString *myString = [[NSString alloc] init];
what is that string's Length value?
The important thing to understand here is that an NSString with no characters in it, such as #"" or [[NSString alloc] init] is still a valid object. All the consequences that Nick has stated follow from that.
In Objective-C, any valid object will be "True" in a boolean context;* nil is the only false object value.
Since these strings are valid objects, they do have a length, but because they contain no characters, the length is 0.
There are no problems with assigning an empty string object #"" to another string pointer, such as the text of your text field. Since the string with no characters is still a valid NSString object, this is exactly the same as assigning a string which does happen to have characters.
*Unlike so-called "scripting" languages like Python or Perl, where an empty string or collection evaluates to boolean false.
Using
theTextField.text = #"";
is absolutely ok. There should be no problems at all.
if (#"")
will evaluate to true. #"" is not the same as nil.
The length of
NSString *myString = [[NSString alloc] init];
is 0.
This is not an answer to the question, but may be the answer to what you're trying to do.
If you're wondering whether you have to write if(str && str.length) to cover both nil and empty strings, you don't. You may use just if(str.length), since, in Objective-C, unknown messages to nil will return nil (so [a.b.c.d.e.f doStuff] will be nil if any of those values in the chain is nil). There is thus scarce need for specific nullity checks, unless what you want is precisely to determine nullity.
Check NSString's + string.
NSString *s1 = #"string1";
// NSString *s2 = [[NSString alloc]stringWithFormat:#"string2"];
NSString *s2 = [[NSString alloc] initWithFormat:#"string2"];
I know this is pretty basic concept but I am not 100% clear with this.
First one doesn't allocate a memory address and send one allocates a memory address...
Also second one increases the reference count of the variable but not the first one...
Even though I understand the concept but don't know the situation when I should use the first one or the second one..
When should I use the first one ? also when should use for the second one?
Thanks in advance..
Carl is is right, but there is some subtlety to keep in mind. Consider this:
NSString *s1 = #"string1";
NSString *s2 = [[NSString alloc] initWithString:#"string1"];
NSString *s3 = [NSString stringWithString:#"string1"];
NSString *s4 = [NSString stringWithFormat:#"string1"];
NSLog(#"ptrs %p %p %p %p", s1, s2, s3, s4);
The output is:
ptrs 0x1000010c0 0x1000010c0 0x1000010c0 0x100108da0
That's right; s1, s2, and s3 are all pointing to the same string instance while s4 ends up being a new instance. This is because NSString detects when a string is being initialized from a constant string and, when perfectly valid to do so, returns the constant string instead of bothering to allocate a new chunk of memory to hold the same thing. The stringWithFormat: case is not so optimized likely because all the potential format string processing makes such an optimization both moot and, likely, unnatural to the implementation.
In other words, do not assume that two strings are the same or different merely by code inspection or by pointer comparison. Use isEqual: or, better yet, isEqualToString:.
You should never use the second one - +stringWithFormat: is a class method. Including your first example, you have basically 3 choices:
NSString *s1 = #"string1";
NSString *s2 = [[NSString alloc] initWithString:#"string2"];
NSString *s3 = [NSString stringWithFormat:#"string3"];
s1 in this case is a pointer to a constant string. s2 and s3 both point to new strings that you've created, but s2 has been retained for you, and s3 has been autoreleased. If you just need a temporary object, the autoreleased object s3 or the constant object s1 are good choices. If you need to keep the string around, you should use s2 (actually now that I think about it s1 will work in this case too - it's not really idiomatic, though).
You can make s1 or s3 equivalent to s2 by sending them a retain message. You could also turn s2 into an equivalent object by sending it an autorelease message.
A string literal like #"string1" (or the #"string2" on the second line) is, as you've noted, not an allocation. The string is actually stored as a constant in your executable's data section, just like any constant you've declared. Strings created this way don't really have a reference count; you can send -retain and -release messages to them and nothing will happen.
Your second line is ill-formed; +stringWithFormat: is actually a class method, and it doesn't really make sense to use +stringWithFormat: without having any format parameters. In general, just use the string literal form if you don't have a specific reason to use another form. There's no need to allocate a new object if there's already the constant one floating around your application.
Don't use any ...WithFormat: method if you're just going to pass it a constant string. No need to parse the format string for the trivial case.