Interrogating an NSArray that appears to have a null entry - ios

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.

Related

NSString in NSMutableArray isn't the same on myString

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 :)

How to pass Array to SOAP API?

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.

Passing a _CFNSString into an NSString

I have a loop that identifies elements of a webpage via its HTML and extracts the sections I need. I'm wanting to build an array or (very) long string of the extracted text which can be used later.
The extraction uses TFHpple from GitHub. The problem seems to lie with the extracted text being a _CFNSString, and these don't allow me to transpose them into a NSString or NSMutuableArray.
The code I'm using is:
NSArray *webNodes = [webParser searchWithXPathQuery:tutorialsXpathQueryString];
NSString *extractedText = [[NSString alloc] init];
NSMutableArray *extractedArray = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in webNodes) {
Extraction *extraction = [[Extraction alloc] init];
[extractedArray addObject:extraction];
extraction.title = [[element firstChild] content];
extractedText = extraction.title;
NSLog(#"\n\nTitle: %#", extractedText);
}
The NSLog at this point shows me extractedText holds I'm after for each loop, breaking the code shows extractedText to be a _CFNSString.
If I try adding
text = [text StringByAppendingString extractedText];
(with 'text' being an NSString initialised before the loop) as the last step of the loop I get a null value. Its the same if I try adding text or extraction.title directly into an array.
I found this question Convert NSCFString to NSString but the conversion seems to be going the other way (NSString to CFNSString). When I added equivalent code I got bridging errors and the code doesn't run.
How can I collect the data within extraction.title to build a string or array that can be used later?
You said you only want a text.
Get it in one line of code for array:
NSArray *extractedArray = [webNodes valueForKeyPath:#"firstChild.content"];
For string:
NSString *extractedText = [webNodes valueForKeyPath:#"firstChild.content"] componentsJoinedByString:#" "];

NSDictionary App Crash

Trying to read a plist and change my font color depending on the option that was selected in the following settings bundle.
The following is how I am trying to accomplish it:
NSString *path = #"/var/mobile/Library/Preferences/NCNotes.plist";
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
fontSize = [[dict objectForKey:#"slideSwitched"] floatValue];
if ([[dict objectForKey:#"noteColor"] valueForKey:#"Purple"]) {
noteView.textColor = [UIColor purpleColor];
} else {
noteView.textColor = [UIColor blackColor];
}
Any ideas why this is why my app is crashing? How do I read the values and change the color depending on what was selected?
It appears that the top level of your plist is an array, not a dictionary, because at the top it says "Item 1" where all of your content is within that. So you have a dictionary within an array. So you can change your code like this:
NSString *path = #"/var/mobile/Library/Preferences/NCNotes.plist";
NSArray *array = [[NSArray alloc] initWithContentsOfFile:path];
NSDictionary *dict = array[0];
You could also change the structure of your plist so that you have a dictionary as the root instead of an array.
Also, keys are supposed to be on the left-hand side and their values on the right-hand side, so I don't see a key "noteColor". You have a key "key" with a value "noteColor", so you'll need to make that correction. I'm also not seeing a "slideSwitched" key, though it might just be outside the bounds of your screenshot.
Also the following won't work:
[[dict objectForKey:#"noteColor"] valueForKey:#"Purple"]
Whatever you get from [dict objectForKey:#"noteColor"] isn't going to be a dictionary, so calling valueForKey: on that isn't going to give you what you want.
simply you should do this with document directory
NSString *contentPath=[[NSBundle mainBundle] pathForResource:#"PLIST_FILE_NAME" ofType:#"plist"];
NSDictionary *dictionary=[NSDictionary dictionaryWithContentsOfFile:contentPath];
write your logic after this, wait a minute , its seems like you dont have a key "noteColor" also. check your plist
Here is some example code documented up the wazoo. Hopefully it will help you understand how these plists and dictionaries work. Everything will be based on your plist file (which could definitely be improved upon, but that's up to you as I don't know your specific situation).
Your question is "How do I find color based on user selection?" I will assume you get the user selection as an int. Something like "User selected 7".
//Load your plist dictionary
NSString *path = #"/var/mobile/Library/Preferences/NCNotes.plist";
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
//Get the array of validValues and the array of validTitles
NSArray *valuesArray = [dict objectForKey:#"validValues"];
NSArray *titlesArray = [dict objectForKey:#"validTitles"];
//Now get the user selected index from the validValues array
int arraySelection = -1;
for(int i = 0; i < [valuesArray count]; i++)
{
NSNumber *number = [valuesArray objectAtIndex:i];
if([number intValue] == userSelectedInput)
{
arraySelection = i;
break;
}
}
if(arraySelection == -1)
{
//Not found in array
return;
}
//Now with that index get the title of the object that the user selected
NSString *userSelectedTitle = [titlesArray objectAtIndex:arraySelection];
//Now do your checking on what the user selected based on that:
if([userSelectedTitle isEqualToString:#"Purple"])
...
You could boil this down quite a bit. Currently your validValues array is completely useless. If it were out of order or missing numbers then it would be needed, but straight counting can be achieved by the validTitles array.

Objective C Array Count String Issue

Okay I am new to objective C and am trying hard to learn it on my own with out bother the stacked overflow community to much but it is really quite different then what I'm used to (C++).
But I have come across a issue that I for the life of me can't figure out and I'm sure it's going be something stupid. But I am pulling questions and answers from a website that then will display on my iOS application by using this code.
NSString * GetUrl = [NSString stringWithFormat:#"http://www.mywebpage.com/page.php"];
NSString * GetAllHtml = [NSString stringWithContentsOfURL:[NSURL URLWithString:GetUrl] encoding:1 error:nil];
NSString *PullWholeQuestion = [[GetAllHtml componentsSeparatedByString:#"<tr>"] objectAtIndex:1];
NSString *FinishWholeQuestion = [[PullWholeQuestion componentsSeparatedByString:#"</tr>"] objectAtIndex:0];
After I get all of the webpage information I strip down each question and want to make it where it will do a loop process to pull the questions so basically I need to count how many array options there are for the FinishedWholeQuestion variable
I found this snippet online that seemed to work with there example but I cant repeat it
NSArray *stringArray = [NSArray arrayWithObjects:#"1", #"2", nil];
NSLog(#"count = %d", [stringArray count]);
"componentsSeparatedByString" returns an NSArray object, not a single NSString.
An array object can contain zero, one or more NSString objects, depending on the input.
If you change "FinishWholeQuestion" into a NSArray object, you'll likely get a few components (separate by a string).
And now that I'm looking at your code a little more closely, I see you're making an assumption that your array is always valid (and has more than 2 entries, as evidenced by the "objectAtIndex: 1" bit).
You should also change the first character of all your Objective-C variables. Best practices in Objective-C are that the first character of variables should always be lower case.
Like this:
NSString * getUrl = [NSString stringWithFormat:#"http://www.mywebpage.com/page.php"];
NSString * getAllHtml = [NSString stringWithContentsOfURL:[NSURL URLWithString:getUrl] encoding: NSUTF8StringEncoding error:nil];
NSArray * allQuestions = [getAllHtml componentsSeparatedByString:#"<tr>"];
if([allQuestions count] > 1)
{
// assuming there is at least two entries in this array
NSString * pullWholeQuestion = [allQuestions objectAtIndex: 1];
if(pullWholeQuestion)
{
NSString *finishWholeQuestion = [[pullWholeQuestion componentsSeparatedByString:#"</tr>"] objectAtIndex:0];
}
}

Resources