I'm trying to use the CFHTTPRequest library to pull data from a web page. All the web page has is a pipe deliminated string of some information about our server status. I want to pull this into the iPhone and display it in a pretty gui interface.
My issue is that i can't figure out how to get the body of the web page. I've looked through a few examples and I keep getting lost. Below is the code i'm using, please give me some idea on how i would get the body, and then throw it into a string where i can then put the data into variables within a class.
Code:
CFHTTPMessageRef request;
CFReadStreamRef stream;
//init: url is a string like "www.someplace.com"
NSString *theURL = [NSString stringWithFormat:@"http://%@", url];
NSURL *urlObj = [NSURL URLWithString:theURL];
request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), (CFURLRef)urlObj, kCFHTTPVersion1_0);
//fetch
stream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault,request);
CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
CFHTTPMessageRef response = (CFHTTPMessageRef) CFReadStreamCopyProperty(stream, kCFStreamPropertyHTTPResponseHeader);
//not sure if this is correct :(
CFDataRef *body = CFHTTPMessageCopyBody(response);
//now what?
Am I heading in the right direction? Or is there a better way to do this?
If I am doing it right, how do I turn body into a string of actual text that I can manipulate?
I figured it out. For anyone that also needs to do this, its simplier then it looks.
Here's the Code:
Code:
NSString *urlStr = [NSString stringWithFormat:@"%@/index.php?some_name=%@", url, name];
NSURL *theURL = [[NSURL alloc] initWithString:urlStr];
//get the data from the web page
NSString * results = [NSString stringWithContentsOfURL:theURL];
//Seperate the data by a | delimiter
NSArray * chunks = [results componentsSeparatedByString:@"|"];
//put the data into some class variables
NSScanner * scanner = [[NSScanner alloc] initWithString:[chunks objectAtIndex:0]];
[scanner scanFloat:&load];
scanner = [[NSScanner alloc] initWithString:[chunks objectAtIndex:3]];
[scanner scanInt:&diskUsage];
users = [[NSString alloc] initWithString:[chunks objectAtIndex:4]];
Hope this helps someone, because this took me HOURS to figure out!
Thanks for that. I can't believe how easy that is. I was just about to start having to figure that out. Now my concern is how to pull data from between two sets of known characters instead of splitting based on a single delimeter. So if anyone has any ideas, I am all ears. Nothing jumps out at me in the API to do this easily. I can figure out the harder way, but didn't know if their was something as simple as splitting was for you.
Thanks for that. I can't believe how easy that is. I was just about to start having to figure that out. Now my concern is how to pull data from between two sets of known characters instead of splitting based on a single delimeter. So if anyone has any ideas, I am all ears. Nothing jumps out at me in the API to do this easily. I can figure out the harder way, but didn't know if their was something as simple as splitting was for you.
You could use the method scanUpToCharactersFromSet:intoString: to find multiple characters, but that won't work for a lot of things, and probably won't work for you here. What you really want is to use regular expressions to do the parsing. AFAIK there is nothing in Coca to handle it, but you could use NSTask to call a command-line function like grep, or Python, Perl, or Ruby script (all of which have built-in support for REs), or use a third-party Cocoa framework.
Pretty odd that Cocoa has no regular expression support directly, a major oversight if you ask me (you'd think it would have been pretty obvious when they were coming up with NSScanner, even back in the NeXT days).
I got it working using NSScanner. Works perfectly.
Code:
- (void) getPilots:(NSString *)data {
NSString *foundData = @"";
NSScanner *scanner = [NSScanner scannerWithString:data];
// loop through the passed html data
while (![scanner isAtEnd]) {
NSInteger leftPos, rightPos;
[scanner scanUpToString: @"left text to find" intoString: nil]; leftPos = [scanner scanLocation];
if (![scanner scanUpToString: @"right text to fin" intoString: nil])
break;
rightPos = [scanner scanLocation] + 1;
leftPos += 19; // add the number of characters of the left text to find
// get data between the left and right text
foundData = [data substringWithRange: NSMakeRange(leftPos, (rightPos - leftPos) - 2)];
[playersArray addObject:foundData];
}
}
Yeah the lack of RegEx seems very odd. After years of using it in .NET I feel naked without it.
If your data is big, consider using NSURLConnection instead-- it allows you to load a URL asynchronously so that your UI doesn't completely lock up. Remember, your users might be stuck with the EDGE network for a while...
If your data is big, consider using NSURLConnection instead-- it allows you to load a URL asynchronously so that your UI doesn't completely lock up. Remember, your users might be stuck with the EDGE network for a while...
Awesome. I was actually wondering about that last night on how not to lock up the view while loading.