I have a single view application where the ViewController contains a UIView of custom class CPTGraphHostingView so that it holds a CorePlot graph. The content of that UIView is managed by an NSObject sub-class called SimpleScatterPlot. This SimpleScatterPlot object holds all the parameters needed to configure the graph (axis ranges, labels, number of points, etc.)
ViewController.h
#import <UIKit/UIKit.h>
#import "CorePlot-CocoaTouch.h"
#import "SimpleScatterPlot.h"
#interface ViewController : UIViewController
{
IBOutlet CPTGraphHostingView *_graphHostingView;
SimpleScatterPlot *_scatterPlot;
NSMutableData *dataConexion;
}
#property (nonatomic,strong) NSArray *valor;
#property (nonatomic,strong) NSArray *strAnoMes;
#property (nonatomic,strong) NSArray *indicador;
#property (nonatomic, retain) SimpleScatterPlot *scatterPlot;
#end
In ViewController.m I have some methods to initialise a few arrays from some JSON data:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize indicador,valor,strAnoMes;
- (void)viewDidLoad
{
[super viewDidLoad];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSString *urlString = #"http://xxxx/ios/datosgrafica.php";
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
(void)[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
dataConexion = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData
{
[dataConexion appendData:theData];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
indicador = [NSJSONSerialization JSONObjectWithData:dataConexion options:nil error:nil];
// ARRAYS OF INTEREST
strAnoMes = [indicador valueForKey:#"StrAnoMes"];
valor = [indicador valueForKey:#"Valor"];
self.scatterPlot = [[SimpleScatterPlot alloc] initWithHostingView:_graphHostingView andData:pointArray];
[self.scatterPlot initialisePlot];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"The download could not complete - please make sure you're connected to either 3G or Wi-Fi." delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[errorView show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
In the SimpleScatterPlot.m I would like to use the array "valor" to configure axis ranges, and I would like to use the array "strAnoMes" to draw custom labels in the xAxis.
What do I have to do so that I can pass those arrays defined in ViewController to SimpleScatterPlot?
I have tried to #import "ViewController.h" but it gives me errors. Any other ideas? What is the best way to approach this situation?
You can take two properties in SimpleScatterPlot.
SimpleScatterPlot.h
#property (nonatomic, retain) NSArray * strAnoMes;
#property (nonatomic, retain) NSArray * valor;
SimpleScatterPlot.m
#synthesize strAnoMes;
#synthesize valor;
In ViewController.m, After creating scatterPlot in connectionDidFinishLoading:, assign the values to above properties as below.
self.scatterPlot.strAnoMes = strAnoMes;
self.scatterPlot.valor = valor;
One way to do this is to create a simple data object and pass it directly into your SimpleScatterPlot object:
Data Object:
#interface SimpleScatterPlotData : NSObject
#property (...) NSArray *valor;
#property (...) NSArray *strAnoMes;
#end
#implementaton SimpleScatterPlotData
#synthesize valar;
#synthesize strAnoMes;
-(void)dealloc
{
...
...
[super dealloc];
}
#end
Implement a load method in your SimpleScatterPlot class:
#interface SimpleScatterPlot
-(void)loadData:(SimpleScatterPlotData *)data;
#end
#implementation SimpleScatterPlot
-(void)loadData:(SimpleScatterPlotData *)data
{
NSArray *valor = data.valor;
NSArray *strAnoMes = data.strAnoMes;
/*
Do something
*/
}
#end
Then in your ViewController class:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
indicador = [NSJSONSerialization JSONObjectWithData:dataConexion options:nil error:nil];
// ARRAYS OF INTEREST
strAnoMes = [indicador valueForKey:#"StrAnoMes"];
valor = [indicador valueForKey:#"Valor"];
SimpleScatterPlotData *data = [[[SimpleScatterPlotData alloc] init] autorelease];
data.valor = valor;'
data.strAnoMes = strAnoMes;
self.scatterPlot = [[SimpleScatterPlot alloc] initWithHostingView:_graphHostingView andData:pointArray];
[self.scatterPlot loadData:data];
}
You could also change your current initializer or add a new initializer to your SimpleScatterPlot class so that you pass those arrays in when you alloc the object. So your the call to your initializer would look something like:
self.scatterPlot = [[SimpleScatterPlot alloc] initWithHostingView:_graphHostingView andData:pointArray andValor:valor andstrAnoMes:strAnoMes];
Then in your initializer you can set the object properties to those passed in values.
Related
So i've done the tutorial where you code a button so that when you press it a sound plays. I'm trying to modify it so that when the button is pressed, a random sound plays.
here is the code:
viewcontroller.h
#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioToolbox.h>
#interface STViewController : UIViewController
- (IBAction)playAudio:(id)sender;
#property (nonatomic, strong) NSArray *sounds;
#end
viewcontroller.m
#import <AVFoundation/AVFoundation.h>
#import "STViewController.h"
#interface STViewController ()
#property (weak, nonatomic) IBOutlet UIButton *playAudio;
#end
#implementation STViewController
- (IBAction)playAudio:(id)sender {
AVAudioPlayer *audioPlayer;
NSString *audioPath = [[NSBundle mainBundle] pathForResource:#"Woof" ofType:#"mp3"];
NSURL *audioURL = [NSURL fileURLWithPath:audioPath];
NSError *audioError = [[NSError alloc] init];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&audioError];
if (!audioError) {
[audioPlayer play];
NSLog(#"Woof!");
}
else {
NSLog(#"Error!");
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I've been dabbling with something along these lines
- (NSArray *)sounds
{
NSArray *sounds = [NSArray arrayWithObjects:
#"Woof.mp3",
#"Meow.mp3",
#"tweet.mp3",
#"Squeak.mp3",
#"Moo.mp3",
#"Croak.mp3",
#"Toot.mp3",
#"Quack.mp3",
#"Blub.mp3",
#"OWOwOw.mp3",
#"Fox.mp3",
nil];
return sounds;
}
but i'm not really sure how to make it random or even implement in in the code that I have going right now. Anyone have any ideas?
Just make it random try below:-
NSMutableArray *array=[NSMutableArray
arrayWithObjects:
#"Woof.mp3",
#"Meow.mp3",
#"tweet.mp3",
#"Squeak.mp3",
#"Moo.mp3",
#"Croak.mp3",
#"Toot.mp3",
#"Quack.mp3",
#"Blub.mp3",
#"OWOwOw.mp3",
#"Fox.mp3",
nil];
// now use exchangeobject with index api
int i=0;
for(i=0;i<=[array count]; i++)
{
NSInteger rand=(arc4random() %10);
[array exchangeObjectAtIndex:i
withObjectAtIndex:rand];
}
I'm developing an iOS application and I'm having some problems when I try to save data.
My code is:
TuplaUsuario:
It is a class where I save user data. In that case, I use mensaje variable, so here is its code:
//TuplaUsuario.h:
#interface TuplaUsuario : NSObject
{
NSMutableString* mensaje;
}
#property NSMutableString* mensaje;
#end
//TuplaUsuario.m:
#import "TuplaUsuario.h"
#implementation TuplaUsuario
#synthesize mensaje;
- (id)initWithString:(NSString *)identifier {
if ( self = [super init] ) {
mensaje = [[NSMutableString alloc] initWithString:identifier];
}
return self;
}
#end
WebService:
It is a class where I communicate with a Web Service.
//WebService.h:
#import "TuplaUsuario.h"
#interface WebService : NSObject {
// Some other data
NSMutableString* message;
TuplaUsuario* usuario;
}
//Declaration of methods
#end
//WebService.m:
#import "WebService.h"
#import "AppDelegate.h"
#implementation WebService
- (id)init:(NSString *)identifier {
self = [super init];
usuario = [[TuplaUsuario alloc] initWithString:#""];
return self;
}
- (void) processComplete: (BOOL)success {
[[self delegate] processSuccessful:success];
AppDelegate* myAppDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
[myAppDelegate setUsuarioActual:usuario];
}
- (void)login:(NSString *)username password:(NSString *)password
{
//Connection with Web Service
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData {
NSDictionary* jsonArray=[NSJSONSerialization
JSONObjectWithData:theData
options:0
error:nil];
message = [jsonArray objectForKey:#"message"];
[usuario setMensaje:message];
}
AppDelegate:
//AppDelegate.h:
#import <UIKit/UIKit.h>
#import "TuplaUsuario.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
Boolean rememberMe;
TuplaUsuario* usuarioActual;
}
#property (strong, nonatomic) UIWindow *window;
#property (retain) TuplaUsuario* usuarioActual;
#end
//AppDelegate.m:
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize usuarioActual;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
usuarioActual = [[TuplaUsuario alloc] initWithString:#""];
return YES;
}
PROBLEM
In WebService, method connection didReceiveData, if I print message variable, it has the correct value, but if I print [usuario mensaje] it prints (null).
Where's my error?
SOLVED
The problem was in my ViewController and init method of WebService. I called init instead of initWithString:
ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
wSProtocol = [[WebService alloc] initWithString:#""]; //Variable of type WebService
}
WebService
- (id)initWithString:(NSString *)identifier {
self = [super init];
usuario = [[TuplaUsuario alloc] initWithString:#""];
return self;
}
Maybe because this method:
- (id)init:(NSString *)identifier {
if ( self = [super init] ) {
mensaje = [[NSMutableString alloc] init];
}
return self;
}
is never called, since you use:
usuario = [[TuplaUsuario alloc] init];
but is still wonder why you pass identifier into the method and never use it. I think you should make it like this:
mensaje = [[NSMutableString alloc] initWithString:identifier];
LoginViewController is my initial view controller. Email address is an input in the LoginViewController and I am trying to send it to FirstViewController. I went through a lot of solutions posted here but was unsuccessful to find a link to my answer.
Please have a look at my code and tell me where I am going wrong. I am stuck at this point from a couple of days. My main problem is that, the output of emailString shows null when I print it to see if it was carried to the FirstViewController.
FYI - I am using storyboard. I have a Tab Bar Controller which has three tabs and FirstViewController is the first tab page.
LoginViewController.h
#import <UIKit/UIKit.h>
#import "FirstViewController.h"
#interface LoginViewController : UIViewController{
NSString *email;
}
- (IBAction)LoginButton:(id)sender;
- (IBAction)CancelButton:(id)sender;
- (IBAction)dismissKeyboard:(id)sender;
#property (weak, nonatomic) IBOutlet UITextField *EmailField;
#property (weak, nonatomic) IBOutlet UITextField *PasswordField;
#end
LoginViewController.m
#import "LoginViewController.h"
#import "FirstViewController.h"
#define USERNAME #"abc#gmail.com"
#interface LoginViewController ()
#end
#implementation LoginViewController
#synthesize EmailField;
#synthesize PasswordField;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
email = [[NSString alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (IBAction)LoginButton:(id)sender {
email = EmailField.text;
if([EmailField.text isEqualToString:USERNAME])
{
FirstViewController *fvc = [[FirstViewController alloc]initWithNibName:#"FirstViewController" bundle:nil];
fvc.emailString = [[NSString alloc] initWithFormat:#"%#",EmailField.text];
// fvc.emailString = email;
[self.navigationController pushViewController:fvc animated:YES];
}
[EmailField resignFirstResponder];
}
- (IBAction)CancelButton:(id)sender {
NSLog(#"Cancel button pressed!!!");
[EmailField resignFirstResponder];
[PasswordField resignFirstResponder];
}
- (IBAction)dismissKeyboard:(id)sender {
[EmailField resignFirstResponder];
[PasswordField resignFirstResponder];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[self LoginButton:nil];
[textField resignFirstResponder];
return YES;
}
#end
FirstViewController.h
#import <UIKit/UIKit.h>
#import "LoginViewController.h"
#interface FirstViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *emailLabel;
#property (nonatomic, retain) NSMutableData *receivedData;
#property (copy) NSString *emailString;
FirstViewController.m
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize emailLabel;
#synthesize receivedData;
#synthesize emailString;
- (void)viewDidLoad
{
[super viewDidLoad];
[emailLabel setText: emailString];
NSString *theURL = [NSURL URLWithString:[NSString stringWithFormat:#"http://.....email=%#",emailString]];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:theURL
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if(connection){
NSLog(#"connection successful");
NSLog(#"%#",emailString);
receivedData = [NSMutableData data];
}
else{
NSLog(#"connection failed");
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[receivedData setLength:0];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSLog(#"Success");
NSLog(#"Received %d bytes of data",[receivedData length]);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
I tried implementing prepareFOrSegue method in LoginViewController too. But it still didnot make any change. This is the code I have written in it.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"showDetailSegue"])
{
NSString *email = EmailField.text;
NSLog (#"++++++++++ %#", email);
FirstViewController *fvc = [segue destinationViewController];
fvc.emailString=email;
}
}
Screenshot of Storyboard:
If you are using StoryBoards I'd strongly suggest you use segues to call the different view controllers. That way you can push vc's and pass info relatively easily.
You can override the native method prepareForSegue in your Login VC, and set the properties there. You can name your segue id as anything in the storyboard.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"firstVC"]) {
FirstViewController *firstVC = [segue destinationViewController];
firstVC.emailString = EmailField.text;
}
}
if you really want, and I'd advise against it vs. using static variables is
NSUserDefaults.
[[NSUserDefaults standardUserDefaults]
setObject:EmailField.text forKey:#"emailString"];
to get it back later
NSString *emailString = [[NSUserDefaults standardUserDefaults]
stringForKey:#"emailString"];
NSLog(#"%#",emailString);
I would save the Email and password in the IOS Keychain securely instead of passing it in between views.
https://developer.apple.com/library/ios/#documentation/security/conceptual/keychainServConcepts/iPhoneTasks/iPhoneTasks.html#//apple_ref/doc/uid/TP30000897-CH208-SW1
I got the solution.
The only three lines requires for me to add in the prepareForSegue were these three and I got my program working
FirstViewController* fvc = [[FirstViewController alloc] init];
UITabBarController *tbc = [segue destinationViewController];
fvc = (FirstViewController *) [[tbc customizableViewControllers] objectAtIndex:0];
Thanks everyone!
I'm using the AFNetworking library to parse json using the AFHTTPClient. I can verify that the json is being parsed within the client block and send that data to my json model. However, when I try to access the json model from outside the block I get no data. How can I pass the parsed json data to the json model then access that model data elsewhere in the app?
the AFHTTPClient subclass / singleton:
#import <Foundation/Foundation.h>
#import "AFHTTPClient.h"
#interface JsonClient : AFHTTPClient
+ (JsonClient *)sharedClient;
#end
#import "JsonClient.h"
#import "AFJSONRequestOperation.h"
static NSString *const kJsonBaseURLString = #"https://alpha-api.app.net/";
#implementation JsonClient
+ (JsonClient *)sharedClient {
static JsonClient *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[JsonClient alloc] initWithBaseURL:[NSURL URLWithString:kJsonBaseURLString]];
});
return _sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (!self) {
return nil;
}
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setDefaultHeader:#"Accept" value:#"application/json"];
return self;
}
#end
the JSON model data:
#import <Foundation/Foundation.h>
#interface TheJson : NSObject
#property (nonatomic, copy) NSString *createdAt;
#property (nonatomic, copy) NSString *userText;
- (id)initWithDictionary:(NSDictionary *)dict;
#end
#import "TheJson.h"
#implementation TheJson
- (id)initWithDictionary:(NSDictionary *)dict {
self = [super init];
if (self) {
self.createdAt = [dict objectForKey:#"created_at"];
self.userText = [dict objectForKey:#"text"];
}
return self;
}
#end
the ViewController to update the user interface:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#end
#import "ViewController.h"
#import "JsonClient.h"
#import "TheJson.h"
#interface ViewController ()
#property (weak) IBOutlet UILabel *createdLabel;
#property (weak) IBOutlet UILabel *textLabel;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (IBAction)fetchJsonData:(id)sender {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
[[JsonClient sharedClient] getPath:#"stream/0/posts/stream/global" parameters:nil
success:^(AFHTTPRequestOperation *operation, id JSON) {
NSArray *postsFromResponse = [JSON valueForKeyPath:#"data"];
NSDictionary *dictFromArray = postsFromResponse[0];
TheJson *jsonObject = [[TheJson alloc] initWithDictionary:dictFromArray];
NSLog(#"createdAt is %#", jsonObject.createdAt);
NSLog(#"text from user is %#", jsonObject.userText);
[self updateInterface];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error is %#", [error description]);
}
];
}
- (void)updateInterface {
TheJson *thejson;
[_createdLabel setText:thejson.createdAt];
[_textLabel setText:thejson.userText];
}
#end
You haven't passed the new jsonObject out of the block nor stored it anywhere. A short term answer is to declare updateInterface to take the jsonObject as a parameter.
So your updateInterface becomes updateInterface: something like this:
- (void)updateInterface:(TheJson*)thejson {
[_createdLabel setText:thejson.createdAt];
[_textLabel setText:thejson.userText];
}
...and then within your block, you call this method like this:
[self updateInterface:jsonObject];
Longer term, if your app has many of these objects and/or needs to hold onto them for any amount of time, you probably want to think about how you will store and organize these as you download them.
I am writing a code that reads data from a http connection and stores in a byte array.
I have written my own NSOperation class. Reference of the code is
Concurrent Operations Demystified
My HttpWorker class declaration is like
#interface HttpWorker : NSOperation{
NSString *param;
double requestCode;
BOOL isLive;
long initSleep;
BOOL _isFinished;
BOOL _isExecuting;
NSURL *_url;
NSURLConnection *_connection;
NSData *_data;
}
#property (nonatomic, retain) NSString *param;
#property (nonatomic) double requestCode;
#property (nonatomic) BOOL isLive;
#property (nonatomic) long initSleep;
#property (readonly) BOOL isFinished;
#property (readonly) BOOL isExecuting;
#property (readonly, copy) NSURL *url;
#property (nonatomic, retain) NSURLConnection *httpCon;
#property (readonly, retain) NSData *data;
-(id)initWithUrl:(NSURL *)_url;
-(void) setRequestParameters:(NSString *)parameters iRequestCode:(double)iRequestCode initialSleep:(long)initialSleep;
#end
And my HttpWorker.m class is like
#import "HttpWorker.h"
#import "Resources.h"
#implementation HttpWorker
#synthesize param;
#synthesize requestCode;
#synthesize isLive;
#synthesize initSleep;
#synthesize isFinished = _isFinished;
#synthesize isExecuting = _isExecuting;
#synthesize url = _url;
#synthesize data = _data;
-(id) initWithUrl: (NSURL *)Url{
self = [super init];
if(self == nil){
return nil;
}
_url = [Url copy];
_isExecuting = NO;
_isFinished = NO;
return self;
}
-(BOOL) isConcurrent{
return YES;
}
-(void) start{
if(![NSThread isMainThread]){
[self performSelectorOnMainThread:#selector(start) withObject:nil waitUntilDone:NO];
return;
}
[self willChangeValueForKey:#"isExecuting"];
_isExecuting = YES;
[self didChangeValueForKey:#"isExecuting"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_url];
NSLog(#"Connecting... %#",_url);
_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately: YES];
if(_connection == nil){
NSLog(#"connection is nil");
}
}
-(void) setRequestParameters:(NSString *)parameters iRequestCode:(double)iRequestCode initialSleep:(long)initialSleep {
self.param = parameters;
self.requestCode = iRequestCode;
self.initSleep = initialSleep;
}
/////////////////////////// delegate methods ///////////////////////////////
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"receieved response...");
_data = [[NSData alloc] init];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)incomingData {
NSLog(#"receieved data...");
}
-(void) connectionDidFinishLoading:(NSURLConnection *) connection {
NSLog(#"connection did finish loading...");
}
#end
Problem is that when i run this code and add httpworker object to the NSOperationQueue, the code runs successfully and _connection is not nil but none of the delegate methods is executed. Can anyone please help?
Thanks and Best Regards...
Your delegate for the connection is "self" (= your NSOperation object). I assume this object is already gone when the connection wants to send messages to the delegate.
Your NSOperation does not have a "main" implementation. Consequently nothing will happen after the thread is started. It will (asynchronously!) fire the NSOperation and quit.
See:
http://developer.apple.com/mac/library/documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html#//apple_ref/occ/instm/NSOperation/main
Bottom line: I highly recommend ASIHTTPRequest for this kind of task.
http://allseeing-i.com/ASIHTTPRequest/