Slide 1

Slide 1 text

Switch to Swift?

Slide 2

Slide 2 text

Early adoption path

Slide 3

Slide 3 text

Swift super powers… … for Switching to Swift

Slide 4

Slide 4 text

1. To be or not to be…

Slide 5

Slide 5 text

public func request(url: NSURL, method: HttpMethod, parameters: [String: AnyObject]?, headers: [String: String]? = nil) -> NSURLRequest { var request = NSMutableURLRequest(…) To be or not to be: optional if headers != nil { for (key,val) in headers! { request.addValue(val, forHTTPHeaderField: key) } } let paramSeparator = request.URL?.query != nil ? "&" : "?" if let headers = headers { for (key,val) in headers { request.addValue(val, forHTTPHeaderField: key) } } aerogear-ios-http

Slide 6

Slide 6 text

2. Don’t store properties Computed properties do not store a value. Instead, they provide a getter and an optional setter to retrieve and set other properties and values indirectly.

Slide 7

Slide 7 text

/** An OAuth2Session implementation to store OAuth2 metadata using Keychain. */ public class TrustedPersistantOAuth2Session: OAuth2Session { private let keychain: KeychainWrap /** The access token. The information is read securely from Keychain. */ public var accessToken: String? { get { return self.keychain.read(self.accountId, tokenType: .AccessToken) } set(value) { if let unwrappedValue = value { let result = self.keychain.save(self.accountId, tokenType: .AccessToken, value: unwrappedValue) } } } Computed properties aerogear-ios-oauth2

Slide 8

Slide 8 text

3. Surrounded by clones Almost all types in Swift are value types, including arrays, dictionary, numbers, booleans, tuples, and enums. Classes are the exception rather than the rule.

Slide 9

Slide 9 text

when to use struct? aerogear-ios-sync

Slide 10

Slide 10 text

4. Define your own matrix Operator overloading! “With great power comes great responsibility,”

Slide 11

Slide 11 text

when to use them in real life? Person { "firstname": "john", "lastname": "doe", "address": { "street": "Buch Street", "poBox": 123, "city": "Glasgow", "country": "UK" } } class Person { var firstname: String? var lastname: String var address: Address? } class Address { var street: String var poBox: Int var city: String var country: String } class Person: JSONSerializable { var firstname: String? var lastname: String var address: Address? required init() {} class func map(source: JsonSZ, object: Person) { object.firstname <= source["firstname"] object.lastname <= source["lastname"] object.address <= source["address"] } } aerogear-ios-jsonsz // serialize from json var serializer = JsonSZ() let developer:Person = serializer.fromJSON(developerJSON, to: Person.self) XCTAssertTrue(developer.firstname == "john") XCTAssertTrue(developer.lastname == "doe")

Slide 12

Slide 12 text

it’s all about type… public func <=(inout left: String?, right: JsonSZ) { if let value = right.value { field = value as? String } } aerogear-ios-jsonsz public func <=(inout left: Int?, right: JsonSZ) { if let value = right.value { field = value as? Int } } public func <=(inout left: Bool?, right: JsonSZ) { if let value = right.value { field = value as? Bool } }

Slide 13

Slide 13 text

5. Go Generic Generics allow a programmer to tell their functions and classes: “I am going to give you a type later and I want you to enforce that type everywhere I specify.” http://swiftyeti.com/

Slide 14

Slide 14 text

it’s all about type… public func <=(inout left: T?, right: JsonSZ) { if let value: AnyObject = right.value { switch T.self { case is String.Type, is Bool.Type, is Int.Type, is Double.Type, is Float.Type: field = value as? T . . . default: field = nil return } } } public func <=(inout left: T?, right: JsonSZ) { if let value = right.value as? [String: AnyObject] { field = JsonSZ().fromJSON(value, to: T.self) } } aerogear-ios-jsonsz

Slide 15

Slide 15 text

6. what about testing? Statically Stubbed or Dynamically Mocked

Slide 16

Slide 16 text

mocking yourself func testRequestAccessWithAuthzCodeFlow() { let expectation = expectationWithDescription("AccessRequestWithAuthzFlow"); let googleConfig = . . . var mock = OAuth2ModulePartialMock(config: googleConfig, session: MockOAuth2Session()) mock.requestAccess { (response: AnyObject?, error:NSError?) -> Void in XCTAssertTrue("ACCESS_TOKEN" == response as String, “response with access token") expectation.fulfill() } waitForExpectationsWithTimeout(10, handler: nil) } public class MockOAuth2Session: OAuth2Session { public override var refreshToken: String? { get {return nil} set(data) {} } public override func tokenIsNotExpired() -> Bool { return false } } class OAuth2ModulePartialMock: OAuth2Module { override func refreshAccessToken( completionHandler:(AnyObject?, NSError?) -> ()) { completionHandler("NEW_ACCESS_TOKEN", nil) } override func requestAuthorizationCode( completionHandler: (AnyObject?, NSError?) -> ()) { completionHandler("ACCESS_TOKEN", nil) } } aerogear-ios-oauth2

Slide 17

Slide 17 text

Swizzling in Swift aerogear-ios-httpstub corinnekrych.org func testSucessfulPOST() { // set up http stub StubsManager.stubRequestsPassingTest({ (request: NSURLRequest!) -> Bool in return true }, withStubResponse: {(request: NSURLRequest!) -> StubResponse in let data = NSJSONSerialization.dataWithJSONObject(["key":"value"], options: nil, error: nil) return StubResponse(data: data!, statusCode: 200, headers: ["head1":"val1"]) }) var http = Http(baseURL: "http://whatever.com") // async test expectation let getExpectation = expectationWithDescription("POST http method test"); http.POST("/post", completionHandler: {(response, error) in XCTAssertNil(error, "error should be nil") XCTAssertTrue(response!["key"] as NSString == "value") getExpectation.fulfill() }) waitForExpectationsWithTimeout(10, handler: nil) }

Slide 18

Slide 18 text

aerogear-ios-sync aerogear-ios-oauth2 aerogear-ios-http aerogear-ios-httpstub aerogear-ios-jsonsz Be smart, code open source