diff --git a/Contentful.xcodeproj/project.pbxproj b/Contentful.xcodeproj/project.pbxproj index ff12a01e..1d625272 100644 --- a/Contentful.xcodeproj/project.pbxproj +++ b/Contentful.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ A114BBC31C50EA3200DE6679 /* SyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A114BBC11C50E9E200DE6679 /* SyncTests.swift */; }; A114BBC51C5107EC00DE6679 /* DeletedResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = A114BBC41C5107EC00DE6679 /* DeletedResource.swift */; }; A119937D1C5252BF00749579 /* DecodableData.swift in Sources */ = {isa = PBXBuildFile; fileRef = A119937C1C5252BF00749579 /* DecodableData.swift */; }; + A127DEC11C56E4E60050EF72 /* Bridging.swift in Sources */ = {isa = PBXBuildFile; fileRef = A127DEC01C56E4E60050EF72 /* Bridging.swift */; }; A17D044D1C4F974F002E568B /* UtilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A17D044C1C4F974F002E568B /* UtilityTests.swift */; }; A19C743F1C47A7F5005334AD /* ContentTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19C743E1C47A7F5005334AD /* ContentTypeTests.swift */; }; A19C74411C47A804005334AD /* EntryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19C74401C47A804005334AD /* EntryTests.swift */; }; @@ -56,6 +57,7 @@ A114BBC11C50E9E200DE6679 /* SyncTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyncTests.swift; sourceTree = ""; }; A114BBC41C5107EC00DE6679 /* DeletedResource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeletedResource.swift; sourceTree = ""; }; A119937C1C5252BF00749579 /* DecodableData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DecodableData.swift; sourceTree = ""; }; + A127DEC01C56E4E60050EF72 /* Bridging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Bridging.swift; sourceTree = ""; }; A15193A91BB91DE700FB83CD /* Space.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Space.swift; sourceTree = ""; }; A15193AB1BB91FED00FB83CD /* ContentType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentType.swift; sourceTree = ""; }; A15193AD1BB9236300FB83CD /* Asset.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Asset.swift; sourceTree = ""; }; @@ -148,6 +150,7 @@ children = ( A19CA3E31B83888200A0EFCD /* Array.swift */, A15193AD1BB9236300FB83CD /* Asset.swift */, + A127DEC01C56E4E60050EF72 /* Bridging.swift */, A19CA3DF1B836F2500A0EFCD /* Client.swift */, A19CA3E11B8386CC00A0EFCD /* Configuration.swift */, A15193AB1BB91FED00FB83CD /* ContentType.swift */, @@ -396,6 +399,7 @@ A19CA3E81B83890D00A0EFCD /* Resource.swift in Sources */, A1B2E3651BBACF2C00814D63 /* Decoding.swift in Sources */, A10FF9D51BBB3676001AA4E9 /* Error.swift in Sources */, + A127DEC11C56E4E60050EF72 /* Bridging.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/Bridging.swift b/Sources/Bridging.swift new file mode 100644 index 00000000..b0e2f83e --- /dev/null +++ b/Sources/Bridging.swift @@ -0,0 +1,51 @@ +// +// Bridging.swift +// Contentful +// +// Created by Boris Bügling on 26/01/16. +// Copyright © 2016 Contentful GmbH. All rights reserved. +// + +/* + This is needed with Swift 2.2 snapshots as of 2016/01/26, probably can go away in the future. + */ + +import Foundation + +#if os(Linux) +func bridge(any: Any) -> AnyObject { + if let any = any as? [String:Any] { return bridge(any) } + + if let any = any as? [Any] { + let array = NSMutableArray() + any.forEach { array.addObject(bridge($0)) } + return array + } + + if let any = any as? String { return NSString(string: any) } + if let any = any as? Bool { return NSNumber(bool: any) } + if let any = any as? Double { return NSNumber(double: any) } + + fatalError("Could not bridge \(any.dynamicType)") +} + +func bridge(dict: [String:Any]) -> NSDictionary { + let result = NSMutableDictionary() + for (key, obj) in dict { + if let obj = obj as? AnyObject { + result.setObject(obj, forKey: NSString(string: key)) + } else { + result.setObject(bridge(obj), forKey: NSString(string: key)) + } + } + return result +} + +func bridge(array: [NSObject:AnyObject]) -> [String:AnyObject] { + var result = [String:AnyObject]() + for (key, value) in array { + result[key.description] = value + } + return result +} +#endif diff --git a/Sources/Client.swift b/Sources/Client.swift index d50d6710..952d602d 100644 --- a/Sources/Client.swift +++ b/Sources/Client.swift @@ -13,6 +13,7 @@ import Interstellar #if os(Linux) import RequestSession +public typealias NSURLResponse = RequestSession.HTTPURLResponse typealias NSURLSession = RequestSession.HTTPSession typealias NSURLSessionConfiguration = RequestSession.HTTPSessionConfiguration public typealias NSURLSessionDataTask = RequestSession.HTTPSessionDataTask @@ -75,8 +76,12 @@ public class Client { private func handleJSON(data: NSData, _ completion: Result -> Void) { do { - let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as! AnyObject +#if os(Linux) + let json = bridge(try NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String : Any]) +#else + let json = try NSJSONSerialization.JSONObjectWithData(data, options: []) if let json = json as? NSDictionary { json.client = self } +#endif completion(.Success(try T.decode(json))) } catch let error as DecodingError { completion(.Error(Error.UnparseableJSON(data: data, errorMessage: error.debugDescription))) @@ -300,7 +305,11 @@ extension Client { */ public func initialSync(matching: [String:AnyObject] = [String:AnyObject](), completion: Result -> Void) -> NSURLSessionDataTask? { var parameters = matching - parameters["initial"] = true as? AnyObject +#if os(Linux) + parameters["initial"] = NSNumber(bool: true) +#else + parameters["initial"] = true +#endif return sync(parameters, completion: completion) } diff --git a/Sources/Decoding.swift b/Sources/Decoding.swift index 15c390f8..306ea1a1 100644 --- a/Sources/Decoding.swift +++ b/Sources/Decoding.swift @@ -29,8 +29,13 @@ private func determineDefaultLocale(json: AnyObject) -> String { } private func parseLocalizedFields(json: AnyObject) throws -> (String, [String:[String:Any]]) { +#if os(Linux) + let fields = bridge((try json => "fields" as! NSDictionary).bridge()) + let locale: String? = ((try? json => "sys" => "locale") as? NSString)?.bridge() +#else let fields = try json => "fields" as! [String:AnyObject] let locale: String? = try? json => "sys" => "locale" +#endif var localizedFields = [String:[String:Any]]() @@ -191,6 +196,17 @@ extension Entry: Decodable { public static func decode(json: AnyObject) throws -> Entry { let (locale, localizedFields) = try parseLocalizedFields(json) +#if os(Linux) + return try Entry( + sys: bridge((json => "sys" as! NSDictionary).bridge()), + localizedFields: localizedFields, + defaultLocale: determineDefaultLocale(json), + + identifier: (json => "sys" => "id" as! NSString).bridge(), + type: (json => "sys" => "type" as! NSString).bridge(), + locale: locale + ) +#else return try Entry( sys: (json => "sys") as! [String : AnyObject], localizedFields: localizedFields, @@ -200,6 +216,7 @@ extension Entry: Decodable { type: json => "sys" => "type", locale: locale ) +#endif } } @@ -234,11 +251,19 @@ extension Field: Decodable { extension Locale: Decodable { /// Decode JSON for a Locale public static func decode(json: AnyObject) throws -> Locale { +#if os(Linux) + return try Locale( + code: (json => "code" as! NSString).bridge(), + isDefault: (json => "default" as! NSNumber).boolValue, + name: (json => "name" as! NSString).bridge() + ) +#else return try Locale( code: json => "code", isDefault: json => "default", name: json => "name" ) +#endif } } @@ -260,6 +285,16 @@ private extension Resource { extension Space: Decodable { /// Decode JSON for a Space public static func decode(json: AnyObject) throws -> Space { +#if os(Linux) + return try Space( + sys: bridge((json => "sys" as! NSDictionary).bridge()), + + identifier: (json => "sys" => "id" as! NSString).bridge(), + locales: json => "locales", + name: (json => "name" as! NSString).bridge(), + type: (json => "sys" => "type" as! NSString).bridge() + ) +#else return try Space( sys: (json => "sys") as! [String : AnyObject], @@ -268,6 +303,7 @@ extension Space: Decodable { name: json => "name", type: json => "sys" => "type" ) +#endif } }