A pattern that we’ve started using at Sabre Labs in our iOS projects is that the view controllers are written in Objective-C and utility classes are written in Swift. We also try to keep as much of the heavy lifting out of the view controllers, so that the VC is responsible for just brokering the information to the view and handling all the necessary delegate methods therein. Anything that a utility class needs to bubble up is handled through a delegate method.
Here is a simple example that hits the SFO API.
First, the header file of the view controller. Note that this has been pulled out of a real project, so I present it here merely as example.
// // ViewController.h // YourProject // // Created by Barrett Clark on 8/25/14. // Copyright (c) 2014 Barrett Clark. All rights reserved. // #import <UIKit/UIKit.h> #import <YourProject-Swift.h> @interface ViewController : UIViewController <SFOProtocol> { SFO *sfo; } @end
And now the implementation file:
// // ViewController.m // YourProject // // Created by Barrett Clark on 8/25/14. // Copyright (c) 2014 Barrett Clark. All rights reserved. // #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. sfo = [[SFO alloc] initWithApiKey:@"sekretkey"]; sfo.delegate = self; [sfo getAirlinesWithOffset:0 limit:5]; [sfo getDiningWithOffset:0 limit:5]; [sfo getPassengerServicesWithOffset:0 limit:5]; [sfo getShoppingWithOffset:0 limit:5]; [sfo getThingsToDoWithOffset:0 limit:5]; } #pragma mark SFO Protocol - (void) didReceiveAirports:(NSArray *)results { NSLog(@"Airports: %@", results); } - (void) didReceiveDining:(NSArray *)results { NSLog(@"Dining: %@", results); } - (void) didReceivePassengerServices:(NSArray *)results { NSLog(@"Passenger Services: %@", results); } - (void) didReceiveShopping:(NSArray *)results { NSLog(@"Shopping: %@", results); } - (void) didReceiveThingsToDo:(NSArray *)results { NSLog(@"Things To Do: %@", results); } @end
And finally, the “utility” file. I don’t generally use AFNetworking. The standard library HTTP calls are good enough for me. Perhaps the completion block that is mostly redundant can be streamlined. I welcome your comments.
// // SFO.swift // YourProject // // Created by Barrett Clark on 8/26/14. // Copyright (c) 2014 Barrett Clark. All rights reserved. // import Foundation @objc protocol SFOProtocol { optional func didReceiveAirports(results: NSArray) optional func didReceiveDining(results: NSArray) optional func didReceiveShopping(results: NSArray) optional func didReceiveThingsToDo(results: NSArray) optional func didReceivePassengerServices(results: NSArray) } @objc class SFO: NSObject { var delegate: SFOProtocol? let queue = NSOperationQueue() var apiKey: NSString let baseURL = "http://www.flysfo.com/api" init(apiKey: NSString) { self.apiKey = apiKey super.init() } /* * Airlines * http://www.flysfo.com/api/airlines.json?limit=20&key=[Your API Key] */ func getAirlines(offset: Int = 0, limit: Int = 30) { var request = requestForURL(limit: limit, offset: offset, endpoint: "airlines") let completion = { (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in let res = response as NSHTTPURLResponse! if ((error) != nil) { println(error.description) return } var error: NSError? if (data != nil) { var e: NSError? var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &e) as NSArray self.delegate?.didReceiveAirports!(jsonResult) } } NSURLConnection.sendAsynchronousRequest(request, queue: self.queue, completionHandler: completion) } /* * Dining * http://www.flysfo.com/api/dining.json?limit=20&key=[Your API Key] */ func getDining(offset: Int = 0, limit: Int = 30) { var request = requestForURL(limit: limit, offset: offset, endpoint: "dining") let completion = { (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in let res = response as NSHTTPURLResponse! if ((error) != nil) { println(error.description) return } var error: NSError? if (data != nil) { var e: NSError? var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &e) as NSArray self.delegate?.didReceiveDining!(jsonResult) } } NSURLConnection.sendAsynchronousRequest(request, queue: self.queue, completionHandler: completion) } /* * Shopping * http://www.flysfo.com/api/shopping.json?limit=20&key=[Your API Key] */ func getShopping(offset: Int = 0, limit: Int = 30) { var request = requestForURL(limit: limit, offset: offset, endpoint: "shopping") let completion = { (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in let res = response as NSHTTPURLResponse! if ((error) != nil) { println(error.description) return } var error: NSError? if (data != nil) { var e: NSError? var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &e) as NSArray self.delegate?.didReceiveShopping!(jsonResult) } } NSURLConnection.sendAsynchronousRequest(request, queue: self.queue, completionHandler: completion) } /* * Things To Do * http://www.flysfo.com/api/things-to-do.json?limit=20&key=[Your API Key] */ func getThingsToDo(offset: Int = 0, limit: Int = 30) { var request = requestForURL(limit: limit, offset: offset, endpoint: "things-to-do") let completion = { (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in let res = response as NSHTTPURLResponse! if ((error) != nil) { println(error.description) return } var error: NSError? if (data != nil) { var e: NSError? var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &e) as NSArray self.delegate?.didReceiveThingsToDo!(jsonResult) } } NSURLConnection.sendAsynchronousRequest(request, queue: self.queue, completionHandler: completion) } /* * Passenger Services * http://www.flysfo.com/api/passenger-services.json?limit=20&key=[Your API Key] */ func getPassengerServices(offset: Int = 0, limit: Int = 30) { var request = requestForURL(limit: limit, offset: offset, endpoint: "passenger-services") let completion = { (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in let res = response as NSHTTPURLResponse! if ((error) != nil) { println(error.description) return } var error: NSError? if (data != nil) { var e: NSError? var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &e) as NSArray self.delegate?.didReceivePassengerServices!(jsonResult) } } NSURLConnection.sendAsynchronousRequest(request, queue: self.queue, completionHandler: completion) } private func requestForURL(#limit: Int, offset: Int, endpoint: NSString) -> NSMutableURLRequest{ let theURL = "\(baseURL)/\(endpoint).json?limit=\(limit)&offset=\(offset)&key=\(apiKey)" let url = NSURL(string: theURL) var request = NSMutableURLRequest(URL: url) request.cachePolicy = .ReloadIgnoringLocalAndRemoteCacheData request.timeoutInterval = 30.0 request.HTTPMethod = "GET" request.setValue("application/json", forHTTPHeaderField: "Accept-Encoding") return request } }