Skip to content

Commit

Permalink
Get rid of force unwraps
Browse files Browse the repository at this point in the history
  • Loading branch information
bmilekic committed Dec 22, 2020
1 parent b682a21 commit 8240dc2
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 51 deletions.
2 changes: 1 addition & 1 deletion Source/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ struct Config {
proto = "http://"
}

var components = URLComponents(string: proto + self.host + "/" + self.app + "/" + path)!
guard var components = URLComponents(string: proto + self.host + "/" + self.app + "/" + path) else { return nil }
components.queryItems = [ URLQueryItem(name: "osdk", value: OptableSDK.version) ]
return components.url
}
Expand Down
25 changes: 14 additions & 11 deletions Source/Core/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,22 @@ class Client {
// Unlike res.value(forHTTPHeaderField:...) which was introduced in iOS 13.0, allHeaderFields is
// case-sensitive, so we need to take special care to perform a case-INsensitive search:
for (key, value) in res.allHeaderFields {
let header = key as! String
let result: ComparisonResult = header.compare(self.passportHeader, options: NSString.CompareOptions.caseInsensitive)
if result == .orderedSame {
self.storage.setPassport(value as! String)
break
if let header = key as? String {
let result: ComparisonResult = header.compare(self.passportHeader, options: NSString.CompareOptions.caseInsensitive)
if result == .orderedSame {
if let pp = value as? String {
self.storage.setPassport(pp)
break
}
}
}
}
}
completionHandler(data, response, error)
}
}

func postRequest(url: URL, data: Any) throws -> URLRequest? {
func postRequest(url: URL, data: Any) throws -> URLRequest {
var req = URLRequest(url: url)
req.httpMethod = "POST"

Expand All @@ -70,14 +73,14 @@ class Client {
req.addValue(passport, forHTTPHeaderField: self.passportHeader)
}

if self.ua != nil {
req.addValue(self.ua!, forHTTPHeaderField: "User-Agent")
if let ua = self.ua {
req.addValue(ua, forHTTPHeaderField: "User-Agent")
}

return req
}

func getRequest(url: URL) throws -> URLRequest? {
func getRequest(url: URL) throws -> URLRequest {
var req = URLRequest(url: url)
req.httpMethod = "GET"

Expand All @@ -88,8 +91,8 @@ class Client {
req.addValue(passport, forHTTPHeaderField: self.passportHeader)
}

if self.ua != nil {
req.addValue(self.ua!, forHTTPHeaderField: "User-Agent")
if let ua = self.ua {
req.addValue(ua, forHTTPHeaderField: "User-Agent")
}

return req
Expand Down
6 changes: 3 additions & 3 deletions Source/Core/LocalStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ class LocalStorage: NSObject {

init(_ config: Config) {
// The key used for storage should be unique to the host+app that this instance was initialized with:
let utf8str = (config.host + "/" + config.app).data(using: .utf8)!.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 0))
let utf8str = (config.host + "/" + config.app).data(using: .utf8)?.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 0))

self.passportKey = self.keyPfx + "_PASS_" + utf8str
self.targetingKey = self.keyPfx + "_TGT_" + utf8str
self.passportKey = self.keyPfx + "_PASS_" + (utf8str ?? "UNKNOWN")
self.targetingKey = self.keyPfx + "_TGT_" + (utf8str ?? "UNKNOWN")
}

func getPassport() -> String? {
Expand Down
8 changes: 4 additions & 4 deletions Source/Edge/Identify.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

import Foundation

func Identify(config: Config, client: Client, ids: [String], completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) throws -> URLSessionDataTask {
let url = config.edgeURL("identify")
let req = try client.postRequest(url: url!, data: ids)
return client.dispatchRequest(req!, completionHandler)
func Identify(config: Config, client: Client, ids: [String], completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) throws -> URLSessionDataTask? {
guard let url = config.edgeURL("identify") else { return nil }
let req = try client.postRequest(url: url, data: ids)
return client.dispatchRequest(req, completionHandler)
}
8 changes: 4 additions & 4 deletions Source/Edge/Profile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

import Foundation

func Profile(config: Config, client: Client, traits: NSDictionary, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) throws -> URLSessionDataTask {
let url = config.edgeURL("profile")
let req = try client.postRequest(url: url!, data: ["traits": traits])
return client.dispatchRequest(req!, completionHandler)
func Profile(config: Config, client: Client, traits: NSDictionary, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) throws -> URLSessionDataTask? {
guard let url = config.edgeURL("profile") else { return nil }
let req = try client.postRequest(url: url, data: ["traits": traits])
return client.dispatchRequest(req, completionHandler)
}
8 changes: 4 additions & 4 deletions Source/Edge/Targeting.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

import Foundation

func Targeting(config: Config, client: Client, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) throws -> URLSessionDataTask {
let url = config.edgeURL("targeting")
let req = try client.getRequest(url: url!)
return client.dispatchRequest(req!, completionHandler)
func Targeting(config: Config, client: Client, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) throws -> URLSessionDataTask? {
guard let url = config.edgeURL("targeting") else { return nil }
let req = try client.getRequest(url: url)
return client.dispatchRequest(req, completionHandler)
}
8 changes: 4 additions & 4 deletions Source/Edge/Witness.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

import Foundation

func Witness(config: Config, client: Client, event: String, properties: NSDictionary, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) throws -> URLSessionDataTask {
let url = config.edgeURL("witness")
let req = try client.postRequest(url: url!, data: ["event": event, "properties": properties])
return client.dispatchRequest(req!, completionHandler)
func Witness(config: Config, client: Client, event: String, properties: NSDictionary, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) throws -> URLSessionDataTask? {
guard let url = config.edgeURL("witness") else { return nil }
let req = try client.postRequest(url: url, data: ["event": event, "properties": properties])
return client.dispatchRequest(req, completionHandler)
}
55 changes: 35 additions & 20 deletions Source/OptableSDK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,25 @@ public class OptableSDK: NSObject {
//
public func identify(ids: [String], _ completion: @escaping (Result<HTTPURLResponse,OptableError>) -> Void) throws -> Void {
try Identify(config: self.config, client: self.client, ids: ids) { (data, response, error) in
guard let response = response as? HTTPURLResponse, error == nil else {
completion(.failure(OptableError.identify("Session error: \(error!)")))
guard let response = response as? HTTPURLResponse, error == nil, data != nil else {
if let err = error {
completion(.failure(OptableError.identify("Session error: \(err)")))
} else {
completion(.failure(OptableError.identify("Session error: Unknown")))
}
return
}
guard 200 ..< 300 ~= response.statusCode else {
var msg = "HTTP response.statusCode: \(response.statusCode)"
do {
let json = try JSONSerialization.jsonObject(with: data!, options: [])
let json = try JSONSerialization.jsonObject(with: data ?? Data(), options: [])
msg += ", data: \(json)"
} catch {}
completion(.failure(OptableError.identify(msg)))
return
}
completion(.success(response))
}.resume()
}?.resume()
}

//
Expand Down Expand Up @@ -178,8 +182,12 @@ public class OptableSDK: NSObject {
//
public func targeting(_ completion: @escaping (Result<NSDictionary,OptableError>) -> Void) throws -> Void {
try Targeting(config: self.config, client: self.client) { (data, response, error) in
guard let response = response as? HTTPURLResponse, error == nil else {
completion(.failure(OptableError.targeting("Session error: \(error!)")))
guard let response = response as? HTTPURLResponse, error == nil, data != nil else {
if let err = error {
completion(.failure(OptableError.targeting("Session error: \(err)")))
} else {
completion(.failure(OptableError.targeting("Session error: Unknown")))
}
return
}
guard 200 ..< 300 ~= response.statusCode else {
Expand All @@ -193,17 +201,17 @@ public class OptableSDK: NSObject {
}

do {
let keyvalues = try JSONSerialization.jsonObject(with: data!, options: [])
let result = keyvalues as? NSDictionary
let keyvalues = try JSONSerialization.jsonObject(with: data ?? Data(), options: [])
let result = keyvalues as? NSDictionary ?? NSDictionary()

// We cache the latest targeting result in client storage for targetingFromCache() users:
self.client.storage.setTargeting(keyvalues as! [String: Any])
self.client.storage.setTargeting(keyvalues as? [String: Any] ?? [String: Any]())

completion(.success(result!))
completion(.success(result))
} catch {
completion(.failure(OptableError.targeting("Error parsing JSON response: \(error)")))
}
}.resume()
}?.resume()
}

//
Expand All @@ -229,11 +237,10 @@ public class OptableSDK: NSObject {
//
@objc
public func targetingFromCache() -> NSDictionary? {
let keyvalues = self.client.storage.getTargeting()
if (keyvalues == nil) {
guard let keyvalues = self.client.storage.getTargeting() as NSDictionary? else {
return nil
}
return (keyvalues! as NSDictionary)
return keyvalues
}

//
Expand All @@ -255,20 +262,24 @@ public class OptableSDK: NSObject {
public func witness(event: String, properties: NSDictionary, _ completion: @escaping (Result<HTTPURLResponse,OptableError>) -> Void) throws -> Void {
try Witness(config: self.config, client: self.client, event: event, properties: properties) { (data, response, error) in
guard let response = response as? HTTPURLResponse, error == nil else {
completion(.failure(OptableError.witness("Session error: \(error!)")))
if let err = error {
completion(.failure(OptableError.witness("Session error: \(err)")))
} else {
completion(.failure(OptableError.witness("Session error: Unknown")))
}
return
}
guard 200 ..< 300 ~= response.statusCode else {
var msg = "HTTP response.statusCode: \(response.statusCode)"
do {
let json = try JSONSerialization.jsonObject(with: data!, options: [])
let json = try JSONSerialization.jsonObject(with: data ?? Data(), options: [])
msg += ", data: \(json)"
} catch {}
completion(.failure(OptableError.witness(msg)))
return
}
completion(.success(response))
}.resume()
}?.resume()
}

//
Expand Down Expand Up @@ -300,20 +311,24 @@ public class OptableSDK: NSObject {
public func profile(traits: NSDictionary, _ completion: @escaping (Result<HTTPURLResponse,OptableError>) -> Void) throws -> Void {
try Profile(config: self.config, client: self.client, traits: traits) { (data, response, error) in
guard let response = response as? HTTPURLResponse, error == nil else {
completion(.failure(OptableError.profile("Session error: \(error!)")))
if let err = error {
completion(.failure(OptableError.profile("Session error: \(err)")))
} else {
completion(.failure(OptableError.profile("Session error: Unknown")))
}
return
}
guard 200 ..< 300 ~= response.statusCode else {
var msg = "HTTP response.statusCode: \(response.statusCode)"
do {
let json = try JSONSerialization.jsonObject(with: data!, options: [])
let json = try JSONSerialization.jsonObject(with: data ?? Data(), options: [])
msg += ", data: \(json)"
} catch {}
completion(.failure(OptableError.profile(msg)))
return
}
completion(.success(response))
}.resume()
}?.resume()
}

//
Expand Down

0 comments on commit 8240dc2

Please sign in to comment.