NSLog string is fine but string into UITextView causes exception [closed] - ios

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
So I have a view controller and in the viewdidload method it's supposed to load some content from a webpage (just a proof of concept, it'll be cached eventually). It gets the content using the tfhipple library and puts the contents into an array, it logs the data to the console and then I want it to apply the contents to a UITextView. However when the view controller is called it gets so far as to log the text to the console but on the line where it sets it as the contents of the UITextView it causes an exception.
NSData *dataURL;
NSString *url = #"http://www.testwebsite.com/testpage.html";
dataURL = [NSData dataWithContentsOfURL: [NSURL URLWithString: url]];
NSString *serverOutput = [[NSString alloc] initWithData:dataURL encoding: NSASCIIStringEncoding];
TFHpple * doc = [[TFHpple alloc] initWithHTMLData:dataURL];
NSArray *elements = [doc searchWithXPathQuery:#"//div[contains(#id,'main-section')]//text()"];
NSString * aboutcontents = [elements objectAtIndex:2];
NSLog(#"test: %#", aboutcontents);
self.aboutbox.text = aboutcontents;
The exception it causes is as follows, along with the console output before hand:
2013-06-24 09:37:51.433 AppName[24765:c07] test: {
nodeContent = "Test Content";
nodeName = text;
raw = "Test Content";
}
2013-06-24 09:37:51.434 AppName[24765:c07] -[TFHppleElement length]: unrecognized selector sent to instance 0x8043be0
2013-06-24 09:37:51.434 AppName[24765:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TFHppleElement length]: unrecognized selector sent to instance 0x8043be0'
*** First throw call stack:
(0x25d012 0x16ebe7e 0x2e84bd 0x24cbbc 0x24c94e 0x76b4fb 0x3347 0x7111c7 0x711232 0x7328c9 0x732704 0x730bda 0x730a5c 0x732647 0x16ff705 0x6332c0 0x633258 0x855ff4 0x16ff705 0x6332c0 0x633258 0x6f4021 0x6f457f 0x6f4056 0x859af9 0x16ff705 0x6332c0 0x633258 0x6f4021 0x6f457f 0x6f36e8 0x662cef 0x662f02 0x640d4a 0x632698 0x22b2df9 0x22b2ad0 0x1d2bf5 0x1d2962 0x203bb6 0x202f44 0x202e1b 0x22b17e3 0x22b1668 0x62fffc 0x2fdd 0x21a5)
libc++abi.dylib: terminate called throwing an exception
(lldb)
I'm a little bit stuck as to why it does this. If I manually set the string aboutcontents to something then it changes the contents of the UITextView without issue.
Any help is as always appreciated.

Try this:
TFHppleElement * aboutcontents = [elements objectAtIndex:2];
NSLog(#"test: %#", [aboutcontents text]);
self.aboutbox.text = [aboutcontents text];
Here is the documentation part taken from hpple:
TFHppleElement * element = [elements objectAtIndex:0];
[e text]; // The text inside the HTML element (the content of the first text node)
[e tagName]; // "a"
[e attributes]; // NSDictionary of href, class, id, etc.
[e objectForKey:#"href"]; // Easy access to single attribute
[e firstChildWithTagName:#"b"]; // The first "b" child node
Try to get attributes for example and see what it returns to you.

you getting resutt for NSString * aboutcontents = [elements objectAtIndex:2]; is a dictionary,convert dictionary into string like this
NSString * aboutcontents=[NSString stringWithFormat:#"%#",[elements objectAtIndex:2]];

Try this.
NSDictionary * aboutcontents = [elements objectAtIndex:2];
NSLog(#"test: %#", aboutcontents);
self.aboutbox.text = [aboutcontents objectForKey:#"nodeContent"];
I don't understand the context but I saw { } in the Log and I guess only dictionaries get printed that way.

Related

ios - get values from NSDictionary

I have JSON on my server, which is parsed into iOS app to NSDictionary. NSDictionary looks like this:
(
{
text = Aaa;
title = 1;
},
{
text = Bbb;
title = 2;
}
)
My question is - how to get just text from first dimension, so it should be "Aaa". I've tried to use this:
[[[json allValues]objectAtIndex:0]objectAtIndex:0];
But it didn't work, it ends with error
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[__NSCFArray allValues]:
unrecognized selector sent to instance 0x714a050'
So can you help me please, how to get just one value from specified index? Thanks!
That error message is simply telling you that NSDictionary (which is the first object of that array, along with the second) doesn't respond to objectAtIndex.
This will be a bit cody, but it explains it better:
NSArray *jsonArray = [json allValues];
NSDictionary *firstObjectDict = [jsonArray objectAtIndex:0];
NSString *myValue = [firstObjectDict valueForKey:#"text"];
Your JSON object is an array, containing two dictionaries. That's how to get the values:
NSDictionary* dict1= json[0];
NSString* text= dict1[#"text"];
NSString* title= dict1[#"title"];
Try this:
NSString *txt = [[json objectAtIndex:0] objectForKey:#"text"];
UPDATE: Have fixed the error. Thanks yunas.

JSON Objective-C Parsing Fail

I have written the following code but I keep on getting nil. I have tried many different variations of this but I am failing exceptionally hard.
This is what I am getting from the server.
Two objects.
[{"description":"yolo.","name":"ye","id":1},{"description":"sMITH","name":"John","id":2}]
Any help would be greatly appreciated...... Thanks.
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
SBJsonParser *jsonParser = [[SBJsonParser alloc] init];
NSArray *jsonObjects = [jsonParser objectWithData:response];
NSMutableString *yolo = [[NSMutableString alloc] init];
for ( int i = 0; i < [jsonObjects count]; i++ ) {
NSDictionary *jsonDict = [jsonObjects objectAtIndex:i];
NSString *IDID = [jsonDict objectForKey:#"id"];
NSString *name = [jsonDict objectForKey:#"name"];
NSLog(#"ID: %#", IDID); // THIS DISPLAYS
[yolo appendString: IDID]; // THIS seems to be causing the new error...
[yolo appendString:#": "];
[yolo appendString: name];
NSLog(#"%#", yolo); // RETURNS NIL
}
EDIT:
currently my new error is...
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[NSDecimalNumber length]:
unrecognized selector sent to instance 0x81b89f0'
Looks like your [jsonDict objectForKey:#"id"] is an NSNumber(or NSDecimalNumber) and not an NSString. You should change the line NSString *IDID = [jsonDict objectForKey:#"id"]; to,
id myObject = [jsonDict objectForKey:#"id"];
NSString *IDID = nil;
if ([myObject isKindOfClass:[NSNumber class]]) {
IDID = [[jsonDict objectForKey:#"id"] stringValue];
} else {
IDID = [jsonDict objectForKey:#"id"];
}
This error appeared now since earlier you were not initializing NSMutableString *yolo and you were using appendString: on a nil object. Since now it is initialized as NSMutableString *yolo = [[NSMutableString alloc] init]; it is trying to call appendString on NSMutableString object which accepts only NSString type as its inputs where as you are passing an NSNumber in it. length is a method which appendString: internally calls. So you need to change this as well.
You never initialize yolo, so it's just nil the whole time you're calling -appendString: on it. Try this:
NSMutableString *yolo = [NSMutableString string];
Have you tried initializing the NSMutableString?
NSMutableString *yolo = [[NSMutableString alloc] init];
It looks like you are not really checking the type of the data coming to your app via your JSON feed. This might be the case of random crashes when users actually use your app. It might be also a reason for rejection to the App Store, is such crashes happen during your App's review.
You should be checking the type of all objects you receive from JSON, before calling methods on them :)
By implementing best practices you will have a stable and usable app. Build data models to validate your data. You can also you a JSON data model framework like JSONModel: http://www.jsonmodel.com/
It's obvious from your data that "id" is not a string, but a number. Assigning a pointer to an NSString* doesn't magically convert it to an NSString*. And it's obvious from the exception that you got that some object is an NSDecimalNumber when you thought it would be an NSString.
So: IDID is an NSNumber*, and pretending it is an NSString* will lead to crashes.

Get Row from NSArray

Hello i get a json that looks like this:
features: (
{
attributes = {
Gecontroleerd = Ja;
};
geometry = {
x = "5.968097965285907";
y = "52.50707112779077";
};
}
)
From this code:
NSDictionary *root = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
NSArray *data = [root objectForKey:#"features"];
NSLog(#"features: %#", data );
for (NSArray *row in data) {
NSString *latitude = row[5];
NSString *longitude = row[7];
NSString *crimeDescription = #"test";
NSString *address = #"banaan";
And u need to x values 5.968097965285907 for latitude
and y values 52.50707112779077 for longitude
But i get this error:
[__NSCFDictionary objectAtIndexedSubscript:]: unrecognized selector sent to instance 0x14831450
2012-11-14 10:10:59.000 ArrestPlotter[6330:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndexedSubscript:]: unrecognized selector sent to instance 0x14831450'
*** First throw call stack:
(0x1860012 0x1655e7e 0x18eb4bd 0x184fbbc 0x184f94e 0x2dbc 0x3b8f 0x1cc1e 0x16696b0 0xfa0035 0x17e3f3f 0x17e396f 0x1806734 0x1805f44 0x1805e1b 0x224a7e3 0x224a668 0x4a765c 0x25bd 0x24e5 0x1)
libc++abi.dylib: terminate called throwing an exception
(lldb)
Does anyone wich row i need to select?
I guess that the only thing is that the row number needs to be changed. Or maybe there should be something like this : [1][5]. Im not quite sure how this works
NSArray *data = [root objectForKey:#"features"];
NSLog(#"features: %#", data );
for (NSDictionary *dic in data) {
NSDictionary geometry = [dic objectForKey:#"geometry"];
// Do what you want..
NSString *myAwesomeX = [geometry objectForKey:#"x"];
NSString *myAwesomeY = [geometry objectForKey:#"y"];
}
The problem here is that you are trying to send a selector message to object row, that is in memory a NSDictionary (NSCFDictionary?) object, and you are trying to manage it like a NSArray.
The method objectAtIndexedSubscript (is underlying called by row[5] and row[7]) exists in NSDictionary, but no in NSArray.
Change
for (NSArray *row in data) {
by
for (NSDictionary *row in data) {
Also, you have to change the management of data inside for, look at the result of your log statement and act accord whit it.
I hope this will help!

iOS thread error when reading from a text file

I'm trying to print an individual element of an array from a text file, here is the code I'm using :
//Tells the compiler where the text file is and its type
NSString* path = [[NSBundle mainBundle] pathForResource:#"shakes"
ofType:#"txt"];
//This string stores the actual content of the file
NSString* content = [NSString stringWithContentsOfFile:path
encoding:NSUTF8StringEncoding
error:NULL];
//This array holds each word separated by a space as an element
NSArray *array = [content componentsSeparatedByString:#" "];
//Fast enumeration for loop tha prints out the whole file word by word
// for (NSString* word in array) NSLog(#"%#",word);
//To access a certain element in an array
NSLog(#"%#", [array objectAtIndex:3
]);
The problem is - if I wish to access the first 2 elements, 0 or 1, that is fine. However, as soon as I wish to access say, element 2 or 3 I get the following error :
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 3 beyond bounds [0 .. 1]
It is a SIGABRT threading error - something which seems to crop a lot in iOS programming, but it's normally quite solvable.
The text file "Shakes.txt" is 6 elements long and is only really for testing purposes.
PS - The third line is commented out just incase I want to use it later... So don't worry about that.
Thanks in advance for any help!
Basically you are trying to access an object which is out of bounds of the array.
The log is very obvious your array only has 1 element and you are trying to access the 4th one.
Add this to your code.
NSMutableArray *contentArray = [[NSMutableArray alloc] init];
for (NSString* word in array)
{
[contentArray addObject:word]
}
//Now try to access contentArray
NSLog(#"%#", [contentArray objectAtIndex:3
]);

EXC_BAD_ACCESS when using stringWithFormat?

While deploying my application, I got the error message: "Thread 1:Program received signal: "EXC_BAD_ACCESS".
My code is below:
-(NSDictionary *)syncWithList:(NSInteger)listID
{
NSString *urlit = [NSString stringWithFormat:#"http://0.0.0.0:3000/lists/%#/syncList.json?auth_token=%#",#"xxxxxxxxxxx",listID];
// **Here I got the error message: "Thread 1:Program received signal: "EXC_BAD_ACCESS"**
NSLog(#"url: %#",urlit);
NSURL *freequestionurl = [NSURL URLWithString:urlit];
ASIHTTPRequest *back = [ASIHTTPRequest requestWithURL:freequestionurl];
[back startSynchronous];
self.listData = [[back responseString] objectFromJSONString];
NSLog(#"%#",listData);
NSDictionary *dicPost = [listData objectAtIndex:0];
return dicPost;
}
Thanks a lot!!!!
You must not format NSInteger (which is just a typedef'd int on current iOS versions) with the %# specifier. Writing %# in a string format basically means "call description on the object and use the result".
But NSInteger is not an object, it's a primitive type.
You get a memory exception because when listID is 42 you access an object at memory address 42. This is definitely not what you want.
-(NSDictionary *)syncWithList:(NSInteger)listID
^^^^^^^^^
NSString *urlit = [NSString stringWithFormat:#"http://0.0.0.0:3000/lists/%#/syncList.json?auth_token=%#",#"xxxxxxxxxxx",listID];
^^
just use the %i format specifier instead of %# for listID.
NSString *urlit = [NSString stringWithFormat:#"http://0.0.0.0:3000/lists/%#/syncList.json?auth_token=%i",#"xxxxxxxxxxx",listID];
EDIT: So used to getting errors from Xcode without it giving me any clues I neglected to notice that the troubled line was already know. I'll leave this here in the hope it helps someone in future.
Try creating an exception breakpoint, it may point to straight to the line where your code is falling over which should help you figure out the problem.
Switch to the breakpoint 'tab' in the left hand navigator.
Click the little '+' at the bottom.
Create a breakpoint as shown in the image:
Run your code and see where it pops.
You used wrong data type to print out.
NSLog(#"%#",listData);
You made very popularar mistake in this line
NSString *urlit = [NSString stringWithFormat:#"http://0.0.0.0:3000/lists/%#/syncList.json?auth_token=%#",#"xxxxxxxxxxx",listID];
Second argument is of type NSInteger, but in format you use %#, this is object only, and compiler thinks that your listID is address of object.
Correct format is %li:
NSString *urlit = [NSString stringWithFormat:#"http://0.0.0.0:3000/lists/%#/syncList.json?auth_token=%li",#"xxxxxxxxxxx",listID];

Resources