Learning Cocoa
February 9th, 2008
Putting things into an NSPopupButton
- it’s easier to use an array of objects with a string property than it is to just use an array of strings. e.g. create a ‘Thing’ class that has a ‘name’ property of type NSString, and put some of them in an NS(Mutable)Array
- you can initialise this array in the
awakeFromNibmethod in your controller - you want to drag an Object from the palette into your MainMenu.nib amd set the Class (in the Identity tab – the ‘i’) to be that of your controller
- then drag an Object Controller into the nib, and control+drag it to your controller (the object you just renamed), selecting the ‘content’ outlet where prompted. Rename this to ControllerAlias (or at least subsitute this where ‘ControllerAlias’ is used below…)
- then, you want an Array Controller as well that will represent the array that’s been initialised in the controller. I named this after the array in my controller
- In the ‘Bindings’ tab (green shapes), expand the ‘Content Array’ section, tick the box and select ‘ControllerAlias’ from the menu. The Controller Key wants to be ‘selection’ and the Model Key Path should be the same as the property of your controller that contains the array of items.
- Your controller should have an IBOutlet for the NSPopupButton you’ve created in the window, so control+drag the NSPopupButton to the Object you created for the controller, and select the outlet when prompted – it will only show you a list of NSPopupButtons (or subclasses).
- Next, select the NSPopupButton in the window (click on it just once, more clicks will select the ‘Cell’ instead, which we don’t want) and then flip to the Bindings tab in the inspector.
- For ‘Content’, tick the box and choose/type the name of the ArrayController you created. The Controller Key wants to be ‘arrangedObjects’, the other two boxes should be empty.
- ‘Content Values’ wants to also be bound to the ArrayController, and again the Controller Key should be ‘arrangedObjects’, but this time the Model Key Path wants to be ‘name’ – or the name you gave to the property on your ‘Thing’s. Finally, the Selected Index also wants to be bound to the ArrayController, with Controller Key set to ‘selectionIndex’
- to get at the value from the controller, setup an IBAction (from a button click or similar) and then you can get at the string value using
[popupbuttonField titleOfSelectedItem]. More useful would be to access the object that you used to bind in the first place, but I can’t seem to get that to work.
Making HTTP POST requests
Coming from PHP, this seems like it’s really complicated, so I wouldn’t be at all surprised if I was missing something…
- To make a request, you need one each of NSURL, NSURLRequest and NSURLConnection. Using NSMutableURLRequest makes the code a bit neater (as you can set properties after initialisation), not sure why you wouldn’t want to use it always? (memory? does ‘mutating’ involve copies?)
- the NSURL is quite basic, just a wrapper around a string:
[url initWithString:@"http://www.example.com"]
- NSURLRequest has initWithURL that takes an NSURL
- To make it a POST request:
setHTTPMethod:@"POST"
- the body of the request can’t just be a string (so far as I understand it…), it has to be an instance of NSData:
NSString* postBody = @"foo=bar&baz=bax";
NSMutableData* requestData = [NSMutableData data];
[requestData appendData:[postBody dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:requestData]; //request is a NSMutableURLRequest
- NSURLConnection has initWithRequest, but uses ‘delegate’ to handle what happens with the response. Using
delegate:selfand defining the prescribed methods on the class you’re calling from is probably the simplest way, but seems to mix concerns a bit too much? - You need to implement didReceiveResponse, didReceiveData, didFailWithError and didFinishLoading. The Apple Docs do a pretty good job of explaining this.
- One thing I did differently though, was change the signature of didReceiveResponse to specify NSHTTPURLResponse (instead of just NSURLResponse) as the parameter-type, as then code-completion gives you the ‘statusCode’ property (200=success, 404=not found etc.).
- The NSHTTPURLResponse class also has a static ‘localizedStringForStatusCode’ method that converts the numbered codes into (presumably localised) strings.
- This will let you know what’s happening, but any action that uses the returned data should be in didFinishLoading
Bear in mind this is the way I’ve discovered to do things. If there are better ways I’d like to know about them!
Leave a Reply