I have an NSString that hold data (actually that could be presented an NSArray). and i want to output that on a label.
In NSLog my NSString output is:
(
"cristian_camino",
"daddu_02",
"_ukendt_babe_",
"imurtaza.zoeb"
)
What i want is, to present it like :"cristian_camino","daddu_02","_ukendt_babe_","imurtaza.zoeb"
In a single line.
I could accomplish that turning string to an array and do following: arrayObjectAtIndex.0, arrayObjectAtIndex.1, arrayObjectAtIndex.2, arrayObjectAtIndex.3.
But thats look not good, and that objects may be nil, so i prefer NSString to hold data.
So, how could i write it in a single lane?
UPDATE:
There is the method i want to use to set text for UILabel:
-(void)setLikeLabelText:(UILabel*)label{
//Likes
NSString* likersCount = [self.photosDictionary valueForKeyPath:#"likes.count"];
NSString* likersRecent = [self.photosDictionary valueForKeyPath:#"likes.data.username"];
NSString *textString = [NSString stringWithFormat:#"%# - amount of people like it, recent "likes": %#", likersCount, likersRecent];
label.text = textString;
NSLog(#"text String is %#", textString);
}
valueForKeyPath: returns an NSArray, not an NSString. Whilst you've declared likersCount and likersRecent as instances of NSString, they're actually both arrays of values. You should be able to do something like the following to construct a string:
NSArray* likersRecent = [self.photosDictionary valueForKeyPath:#"likes.data.username"];
NSString *joined = [likersRecent componentsJoinedByString:#"\", \""];
NSString *result = [NSString stringWithFormat:#"\"%#\"", joined];
NSLog(#"Result: %#", result);
componentsJoinedByString: will join the elements of the array with ", ", and then the stringWithFormat call will add a " at the beginning and end.
The statement is incorrect, the internal quote marks (" that you want to display) need to be escaped:
NSString *textString = [NSString stringWithFormat:#"%# - amount of people like it, recent \"likes\": %#", likersCount, likersRecent];
If somebody curious how i fix it, there it is:
for (int i =0; i < [likersRecent count]; i++){
stringOfLikers = [stringOfLikers stringByAppendingString:[NSString stringWithFormat:#" %#", [likersRecent objectAtIndex:i]]];
}
Not using commas or dots though.
Related
I created three string, that bind it data with method argument. However, i face issue that all of three string share same memory, therefore, it show the same text. Here is how i create it:
-(void)buildViewsWIithTitle:(NSString*)eventTitle{
NSString *firstStr = #"";
NSString *secondStr = #"";
NSString *thirdStr = #"";
Next i set label text to all of this three string. I set it value like:
thirdStr = [NSString stringWithFormat:#"%#", eventTitle];
secondStr = [NSString stringWithFormat:#"%#", eventTitle]
firstStr = [NSString stringWithFormat:#"%#", eventTitle];
In console i output its memory just after creation:
NSLog(#"memory %p , %p , %p", firstStr, secondStr, thirdStr);
memory 0x109af82d8 , 0x109af82d8 , 0x109af82d8
Any idea how make memory address different for them?
As you are using NSString for all 3 objects, which can't be mutated, The compiler will check the value of the string, which is the same empty to all strings. The compiler will optimise the memory usage by pointing the same memory.
The iOS compiler optimizes references to string objects that have the same value (i.e., it reuses them rather than allocating identical string objects redundantly), so all three pointers are in fact pointing to same address.
If you used the NSMutableString, still it may point to the same object, but when you try to mutate the string, it will be copied to the new memory(Lazy memory allocation).
if you want the different memory for each string then you can allocate the memory then initialize the string, like
NSMutableString *str1 = [[NSMutableString alloc]initWithString:#""]
NSMutableString *str2 = [[NSMutableString alloc]initWithString:#""]
NSMutableString *str3 = [[NSMutableString alloc]initWithString:#""]
But note that NSMutableString is mutable.
That's because your all string have address of [NSString stringWithFormat:#"%#", eventTitle]; and this is same for all strings.
For example if you will write below code in your viewdidload then you will get different memory address,
NSString *firstStr = #"";
NSString *secondStr = #"";
NSString *thirdStr = #"";
thirdStr = [NSString stringWithFormat:#"%#", #"eventTitle"];
secondStr = [NSString stringWithFormat:#"%#", #"eventTitle"];
firstStr = [NSString stringWithFormat:#"%#", #"eventTitle"];
NSLog(#"memory %p , %p , %p", firstStr, secondStr, thirdStr);
Because everystring has own memory and not pointing to any single string.
Maybe there's some kind of compiler optimisation going on. It determines (correctly) that the strings are the same so it optimises while compiling. As soon as you change your code so the strings will not be the same and recompile then the compiler won't optimise those particular strings.
thirdStr = [NSString stringWithFormat:#"a %#", eventTitle];
secondStr = [NSString stringWithFormat:#"b %#", eventTitle];
firstStr = [NSString stringWithFormat:#"c %#", eventTitle];
I am trying to get single characters from NSString, like "ઐતિહાસિક","પ્રકાશન","ક્રોધ". I want output like 1)ઐ,તિ,હા,સિ,ક 2) પ્ર,કા,શ,ન 3) ક્રો,ધ, but output is coming like this 1)ઐ , ત , િ , હ , િ , ક 2) પ , ્ , ર , ક , ા , શ , ન 3)ક , ્ , ર , ો , ધ
I have used code like below:
NSMutableArray *array = [[NSMutableArray alloc]init];
for (int i=0; i<strElement.length; i++)
{
NSString *str = [strElement substringWithRange:NSMakeRange(i, 1)];
[array addObject:str];
}
NSLog(#"%#",array);
Let's take strElement as "ક્રોધ" then I got output like this ક , ્ , ર , ો , ધ
But I need output like this ક્રો,ધ
Is there any way that I can get the desired output? Any method available directly in iOS or need to create it by my self then any way or idea how to create it?
Any help is appreciated
Your code is assuming that each character in the string is a single unichar value. But it is not. Some of the Unicode characters are composed of multiple unichar values.
The solution is to use rangeOfComposedCharacterSequenceAtIndex: instead of substringWithRange: with a fixed range length of 1.
NSString *strElement = #"ઐતિહાસિક પ્રકાશન ક્રોધ";
NSMutableArray *array = [[NSMutableArray alloc]init];
NSInteger i = 0;
while (i < strElement.length) {
NSRange range = [strElement rangeOfComposedCharacterSequenceAtIndex:i];
NSString *str = [strElement substringWithRange:range];
[array addObject:str];
i = range.location + range.length;
}
// Log the results. Build the results into a mutable string to avoid
// the ugly Unicode escapes shown by simply logging the array.
NSMutableString *res = [NSMutableString string];
for (NSString *str in array) {
if (res.length) {
[res appendString:#", "];
}
[res appendString:str];
}
NSLog(#"Results: %#", res);
This outputs:
Results: ઐ, તિ, હા, સિ, ક, , પ્ર, કા, શ, ન, , ક્રો, ધ
This question already has answers here:
Split an NSString to access one particular piece
(7 answers)
Closed 9 years ago.
I want to filter string after character '='. For eg if 8+9=17 My output should be 17. I can filter character before '=' using NSScanner, how to do its reverse??? I need a efficient way to do this without using componentsSeparatedByString or creating an array
Everyone seems to like to use componentsSeparatedByString but it is quite inefficient when you just want one part of a string.
Try this:
NSString *str = #"8+9=17";
NSRange equalRange = [str rangeOfString:#"=" options:NSBackwardsSearch];
if (equalRange.location != NSNotFound) {
NSString *result = [str substringFromIndex:equalRange.location + equalRange.length];
NSLog(#"The result = %#", result);
} else {
NSLog(#"There is no = in the string");
}
Update:
Note - for this specific example, the difference in efficiencies is negligible if it is only being done once.
But in general, using componentsSeparatedByString: is going to scan the entire string looking for every occurrence of the delimiter. It then creates an array with all of the substrings. This is great when you need most of those substrings.
When you only need one part of a larger string, this is very wasteful. There is no need to scan the entire string. There is no need to create an array. There is no need to get all of the other substrings.
NSArray * array = [string componentsSeparatedByString:#"="];
if (array)
{
NSString * desiredString = (NSString *)[array lastObject]; //or whichever the index
}
else
{
NSLog(#""); //report error - = not found. Of array could somehow be not created.
}
NOTE:
Though this is very popular splitting solution, it is only worth trying whenever every substring separated by separator string is required. rmaddy's answer suggest better mechanism whenever the need is only to get small part of the string. Use that instead of this approach whenever only small part of the string is required.
Try to use this one
NSArray *arr = [string componentsSeparatedByString:#"="];
if (arr.count > 0)
{
NSString * firstString = [arr objectAtIndex:0];
NSString * secondString = [arr objectAtIndex:1];
NSLog(#"First String %#",firstString);
NSLog(#"Second String %#",secondString);
}
Output
First String 8+9
Second String 17
Use this:
NSString *a =#"4+6=10";
NSLog(#"%#",[a componentsSeparatedByString:#"="])
;
Log: Practice[7582:11303] (
"4+6",
10
)
Will this bit of code produce any memory leaks? Is it the correct way to change NSString values?
NSString * enemiesAndElementsTextureFileName = #"bla bla";
enemiesAndElementsTextureFileName = #"bl";
That way of doing it won't cause any memory leaks and it is indeed correct. In this case you wouldn't need an NSMutableString because you aren't altering the string literal itself, you are simply replacing the string value with a new one (replacing #"bla bla" with #"bl").
In this case, however, your string will now be 'bl', so you can delete that first line value and just have NSString * enemiesAndElementsTextureFileName = #"bl";
Yes NSString allocated once. This is one of the way
Yes, use NSMutableString with the following method as your needs:
// Allocate
NSMutableString *str = [[NSMutableString alloc] initWithCapacity:10];
// set string content
[str setString:#"1234"];
// Append
[str appendString:#"567"];
// Concat
[str appendFormat:#"age is %i and height is %.2f", 27, 1.55f];
// Replace
NSRange range = [str rangeOfString:#"height"];//查找字符串height的位置
[str replaceCharactersInRange:range withString:#"no"];
// Insert
[str insertString:#"abc" atIndex:2];
// Delete
range = [str rangeOfString:#"age"];
[str deleteCharactersInRange:range];
NSLog(#"%#", str);
I have several NSStrings which I add to an NSArray. The string may contain special characters. In the end I want to print the array to a UILabel.
The very simplified code (if you think I missed something, let me know):
NSString *strBuffer = #"Röckdöts";
NSLog(#"String: %#", strBuffer);
NSMutableArray *marrSelectedStrings = [[NSMutableArray alloc] init];
[marrSelectedStrings addObject:strBuffer];
NSLog(#"Array: %#", marrSelectedStrings);
NSUInteger iCount = [marrSelectedStrings count]
for (NSUInteger i = 0; i < iCount; i++)
{
NSLog(#"element %d: %#", i, [marrSelectedStrings objectAtIndex: i]);
}
In a different UIViewController:
self.label.text = [NSString stringWithFormat:#"%#", marrSelectedStrings];
The string itself prints out fine. For the array however, it depends on the output method, whether the console diplays the correct special character or code for it. The label only prints code instead of the real characters. The print out via NSLog looks like the following:
Buffer: Röckdöts
Array: (
R\U00f6ckd\U00f6ts
)
element 0: Röckdöts
Whereas the label reads:
R\U00f6ckd\U00f6ts
I tried using stringWithUTF8String during the adding to the array as well as encoding during assigning it to the label like so, but it didn't change the result:
// adding with UTF8 encoding
[marrSelectedStrings addObject:[NSString stringWithUTF8String:[strBuffer UTF8String]]];
// printing to label with UTF8 encoding
self.label.text = [NSString stringWithUTF8String:[[NSString stringWithFormat:#"%#", marrSelectedStrings] UTF8String]];
Is there an easier way to simply print the array with correct character encoding to the UILabel than iterating over the array and appending every single word?
Try this
NSString * result = [[marrSelectedStrings valueForKey:#"description"] componentsJoinedByString:#""];
self.label.text = result;
try like this
NSMutableArray *marrSelectedStrings = [[NSMutableArray alloc] init];
[marrSelectedStrings addObject:strBuffer];
NSString *description = [marrSelectedStrings description];
if (description) {
const char *descriptionChar = [description cStringUsingEncoding:NSASCIIStringEncoding];
if (descriptionChar) {
NSString *prettyDescription = [NSString stringWithCString:descriptionChar encoding:NSNonLossyASCIIStringEncoding];
if (prettyDescription) {
description = prettyDescription;
}
}
}
NSLog(#"Array: %#", description);