I have a problem with NSString and NSMutableArray.
When I retrieve a string from mutable array ,it has more white spaces, and I don't understand why it's happening.
I'll explain, I have an array and populate it by query (using sqlite3):
NSMutableArray *fileNameAttached = [[NSMutableArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
and it's like this:
<__NSArrayM 0x15e233980>(
<__NSArrayM 0x15e26afd0>(
Allegato N. 1
)
)
When I retrieve the string Allegato N.1 with this code:
NSString *test = [NSString stringWithFormat:#"%#", [fileNameAttached objectAtIndex:0] ];
string test is like this:
(
"Allegato N. 1"
)
Why my string isn't only:
Allegato N.1
When I put it in a label it's not correct because contains () and white spaces.
The query for DB is:
NSString *query = [NSString stringWithFormat:#"SELECT fileName FROM Attach WHERE ID = '%#';",ticketID];
and works perfectly,in fact when I populate tableview cell it's OK. But I don't understand because my string test contains 3 line with more white spaces.
Please help Me.
Thank you and sorry for my english.
In your log there are two arrays.
(
(
Allegato N. 1
)
)
There are two round brackets thats means two array.
You are fetching data like NSString *test = [NSString stringWithFormat:#"%#", [fileNameAttached objectAtIndex:0] ];
That means first object of outer array so it is another array. so you need to do something like
NSArray *temp =[fileNameAttached objectAtIndex:0];
NSString *test = [NSString stringWithFormat:#"%#", [temp objectAtIndex:0] ];
I think you are using appcoda's DBManager class to do this. If it is so then you everytime got two array when load query.
Hope this will help :)
Related
I need to pass this array to SOAP API as a parameter. The back-end guy is new to building APIs (C#/.NET) and I have never implemented this kind of API before. There are 4-5 SO question related to this. But none of them were the solution as per my query.
NSArray *arr = [NSArray arrayWithObjects:#"1",#"2", nil];
NSString *soapURL = #"http://tempuri.org/IService1/addRecord";
NSString *soapBody = [NSString stringWithFormat:#"<addRecord xmlns=\"http://tempuri.org/\">"
"<id>%#</id>"
"<title>%#</title>"
"<record>%#</record>"
"</addRecord> \n” ,#“1”,#“abc", arr ];
NSLog(#"%#",soapBody);
Error:
value in string The formatter threw an exception while trying to deserialize the message: Error in deserializing body of request message for operation 'addRecord'. End element 'record' from namespace 'http://tempuri.org/' expected. Found text '(
1,
2
)'.
One thing I came to know that I cannot pass array directly in to soapBody. What what is the alternative?
The API is working fine at the back-end.
some comments:
NSArray *arr = [NSArray arrayWithObjects:#"1",#"2", nil];
please write instead the modern form:
NSArray *arr = #[#"1",#"2"];
Also, your question is filled with wrong types of quotes (“1”). Make sure to use the regular quotes, i.e. ".
When you use "stringWithFormat" with %# and provide an array, you must understand what you are getting there. let's try:
NSArray *arr = #[#"1",#"2"];
NSString *str = [NSString stringWithFormat:#"<%#>", arr];
NSLog(#"%#", str);
The result is:
<(
1,
2
)>
It means that between your <record> and </record> you inserted two numbers separated by a comma and surrounded by parentheses, plus some \n.
Is this what your server is expecting?
So I am not solving your problem, but you must format your string the right way and verify it using your NSLog command. Hoping it is helping.
EDIT
If for example you need to provide the values of the array within <value>...</value> than you can do this:
NSArray *arr = #[#"1", #"2"];
NSMutableString *mStr = [NSMutableString string];
for (NSString *value in arr) {
[mStr appendFormat:#"<value>%#</value>", value];
}
NSLog(#"<record>%#</record>", mStr);
And the result will be
<record><value>1</value><value>2</value></record>
Finally I resolved this issue with this code:
NSString *soapBody = [NSString stringWithFormat:#"< addRecord xmlns=\"http://tempuri.org/\" xmlns:arr=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\" > \n"
"<ID>1</ID>\n"
"<title>ABC</title>\n"
"<record>\n"];
for (int i=0; i<arrRecord.count; i++) {
soapBody = [NSString stringWithFormat:#"%# <arr:int>%#</arr:int>\n",soapBody,arrRecord[i]];
}
soapBody = [NSString stringWithFormat:#"%# </record></addRecord> \n",soapBody];
I needed to define "arr" in the parent node and type of element(int) in the record array.
Hi I am trying to extract key value from NSDictionary, the dictionary value looks like below screen shot
I need to extract the value with key "TITLE" to NSString, using the code
NSDictionary* tmp = [self getDBRequest:req];
NSString * title =[tmp valueForKey:#"TITLE"];
But giving the the value like
Is there anything wrong with above code?
Edit:
NSLog(#"%#", tmp);
Gives the output
2015-12-31 11:04:52.530 SimpleTable[610:10059] (
{
DESCRIPTION = "30% OFF ON NEW ";
"IMAGE_URL" = "crowd.jpg";
TITLE = "GET 30% OFF";
}
)
Edit2
Actualy using the result of NSString * title =[tmp valueForKey:#"TITLE"]; I have to replace an element of NSMutableArray
And the code
NSMutableArray *array = [[NSMutableArray alloc]init];
[array addObject:#"Eezy"];
[array addObject:#"Tutorials"];
NSDictionary* tmp = [self getDBRequest:req];
NSString * title =[tmp valueForKey:#"TITLE"];
[array replaceObjectAtIndex:0 withObject:title];
Giving me the array modified some thing like below screen shot
Look at the first image in your question, the first line of the contents dump says "1 object".
Also look at the output of the NSLog, notice the parentheses (( & )) which surround the braces ({ & }), which in turn surround the key/value pairs.
Both these are telling you that tmp is not referencing an NSDictionary as you think, but an NSArray containing a single element and that element is an NSDictionary.
Now when you invoke valueForKey: on an array of dictionaries it does the key lookup on every dictionary in the collection and returns and array of results.
Which is why when you look at the second image in your question you see that its contents dump also starts with "1 object" - title is referencing an array containing one element, being your string.
This is also why, as mentioned in the comments, that using objectForKey: in place of valueForKey: causes an error - that method does not operate on arrays and so produces the unrecognized selector sent to instance error.
HTH
try like bellow code.
NSDictionary *tmp = #{#"DESCRIPTION" : #"30 OFF ON NEW",#"IMAGE_URL" : #"crowd.jpg",#"TITLE" : #"GET 30% OFF"};
//NSDictionary* tmp = [self getDBRequest:req];
NSArray *keyArray = [tmp allKeys];
NSString * title = [keyArray objectAtIndex:[keyArray indexOfObject:#"TITLE"]];//[keyArray objectAtIndex:0];
[array replaceObjectAtIndex:0 withObject:title];
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.
I have scenarios in which I may have an NSString that contains several words, some of them duplicated. What I want to do is take a string that looks like:
One Two Three Three Three Two Two Two One One Two Three
and make it look like:
One Two Three
There may be times that the exact length of the original NSString is different as well. What I have so far is:
NSString *hereitis = #"First Second Third Second Third First First First";
NSArray *words = [hereitis componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSCountedSet *countedSet = [NSCountedSet setWithArray:words];
NSMutableArray *finalArray = [NSMutableArray arrayWithCapacity:[words count]];
for(id obj in countedSet) {
if([countedSet countForObject:obj] == 1) {
[finalArray addObject:obj];
}
}
NSString *string = [finalArray componentsJoinedByString:#" "];
NSLog(#"String%#", string);
This however, just returns String in my array, and not ANY of the words.
This can actually be done way less painlessly. NSSet doesn't allow duplicate entries. So, you can break the string into an array, and use that array to create the set. From there, all you have to do is convert back, and the dupes will be removed.
NSString *inputString = #"One Two Three Three Three Two Two Two One One Two Three";
NSSet *aSet = [NSSet setWithArray:[inputString componentsSeparatedByString:#" "]];
NSString *outputString = [aSet.allObjects componentsJoinedByString:#" "];
NSLog(#"___%#___",outputString); // Outputs "___One Two Three___"
You will get an array of strings then
for(id obj in countedSet) {
if([countedSet countForObject:obj] == 1) {
[finalArray addObject:obj];
}
}
After that you can use your words
NSLog(#"%#", finalArray[0]); //log 'One'
You can use KVC Collection Operators for this as well:
NSString *string = #"One Two Three Three Three Two Two Two One One Two Three";
NSArray *items = [string componentsSeparatedByString:#" "];
NSArray *uniqueItems = [items valueForKeyPath:#"#distinctUnionOfObjects.self"];
I have an iPad app that links to an SQL database to retrieve information in the following way:
NSString *strGetCodeUrl = [NSString stringWithFormat:#"%#", #"http://website/getdevicecode.php?device=" , deviceName];
NSArray *deviceArray = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strGetCodeUrl]];
This works when there is a device that matches and it retrieves the required information. However if there is not a match it returns
("")
The array however appears to have one record. Ideally I would like to stop this from happening and for the array to be empty if there is no match. Alternatively (although not very tidy) I could check the length of the entry at index 0 but I am struggling with this method.
NSString *deviceCode = [deviceArray objectAtIndex:0];
if ( [deviceCode length] == 0)
{
device does not exist
}
Any advice gratefully received.
What about this:
NSString *deviceCode = [deviceArray objectAtIndex:0];
if ([deviceCode isEqualToString:#""])
{
device does not exist
}
I don't think you can tell the init method to leave out empty strings...
However, you can do this:
NSString *strGetCodeUrl = [NSString stringWithFormat:#"%#", #"http://website/getdevicecode.php?device=" , deviceName];
NSArray *deviceArray = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strGetCodeUrl]];
[deviceArray removeObject:#""];
Which also isn't as tidy as perhaps you were hoping for, but it will remove all empty strings. But at least its just 1 line of code as opposed to about 3 for the if
Per the documentation:
Removes all occurrences in the array of a given object.