├── .swift-version ├── Pods ├── Target Support Files │ ├── Alamofire │ │ ├── Alamofire-prefix.pch │ │ ├── Alamofire.modulemap │ │ ├── Alamofire-dummy.m │ │ ├── Alamofire-umbrella.h │ │ ├── Alamofire.xcconfig │ │ └── Info.plist │ ├── MagicMapper │ │ ├── MagicMapper-prefix.pch │ │ ├── MagicMapper.modulemap │ │ ├── MagicMapper-dummy.m │ │ ├── MagicMapper-umbrella.h │ │ ├── MagicMapper.xcconfig │ │ └── Info.plist │ ├── AlamofireImage │ │ ├── AlamofireImage-prefix.pch │ │ ├── AlamofireImage.modulemap │ │ ├── AlamofireImage-dummy.m │ │ ├── AlamofireImage-umbrella.h │ │ ├── AlamofireImage.xcconfig │ │ └── Info.plist │ └── Pods-MagicMapper-Example │ │ ├── Pods-MagicMapper-Example.modulemap │ │ ├── Pods-MagicMapper-Example-dummy.m │ │ ├── Pods-MagicMapper-Example-umbrella.h │ │ ├── Info.plist │ │ ├── Pods-MagicMapper-Example.debug.xcconfig │ │ ├── Pods-MagicMapper-Example.release.xcconfig │ │ ├── Pods-MagicMapper-Example-frameworks.sh │ │ ├── Pods-MagicMapper-Example-resources.sh │ │ ├── Pods-MagicMapper-Example-acknowledgements.markdown │ │ └── Pods-MagicMapper-Example-acknowledgements.plist ├── Manifest.lock ├── Local Podspecs │ └── MagicMapper.podspec.json ├── Alamofire │ ├── LICENSE │ └── Source │ │ ├── DispatchQueue+Alamofire.swift │ │ ├── Notifications.swift │ │ ├── Result.swift │ │ ├── Timeline.swift │ │ ├── NetworkReachabilityManager.swift │ │ ├── Response.swift │ │ ├── Validation.swift │ │ ├── ServerTrustPolicy.swift │ │ └── ParameterEncoding.swift └── AlamofireImage │ ├── LICENSE │ └── Source │ ├── Image.swift │ ├── AFIError.swift │ ├── UIImage+AlamofireImage.swift │ ├── ImageCache.swift │ └── Request+AlamofireImage.swift ├── MagicMapper.xcodeproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── Podfile ├── MagicMapper.xcworkspace └── contents.xcworkspacedata ├── MagicMapper ├── Int+Mappable.swift ├── Double+Mappable.swift ├── String+Mappable.swift ├── Dictionary+Mappable.swift ├── Bool+Mappable.swift ├── Array+Mappable.swift ├── Info.plist ├── Dictionary+Value.swift └── Mappable.swift ├── Podfile.lock ├── MagicMapper.podspec ├── MagicMapper-Example ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── AppDelegate.swift └── ViewController.swift ├── .gitignore ├── README.md └── LICENSE /.swift-version: -------------------------------------------------------------------------------- 1 | 3.0 2 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MagicMapper/MagicMapper-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Pods/Target Support Files/AlamofireImage/AlamofireImage-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire.modulemap: -------------------------------------------------------------------------------- 1 | framework module Alamofire { 2 | umbrella header "Alamofire-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Alamofire : NSObject 3 | @end 4 | @implementation PodsDummy_Alamofire 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MagicMapper/MagicMapper.modulemap: -------------------------------------------------------------------------------- 1 | framework module MagicMapper { 2 | umbrella header "MagicMapper-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MagicMapper/MagicMapper-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_MagicMapper : NSObject 3 | @end 4 | @implementation PodsDummy_MagicMapper 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/AlamofireImage/AlamofireImage.modulemap: -------------------------------------------------------------------------------- 1 | framework module AlamofireImage { 2 | umbrella header "AlamofireImage-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/AlamofireImage/AlamofireImage-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_AlamofireImage : NSObject 3 | @end 4 | @implementation PodsDummy_AlamofireImage 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double AlamofireVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char AlamofireVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MagicMapper/MagicMapper-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double MagicMapperVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char MagicMapperVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/AlamofireImage/AlamofireImage-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double AlamofireImageVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char AlamofireImageVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MagicMapper-Example/Pods-MagicMapper-Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_MagicMapper_Example { 2 | umbrella header "Pods-MagicMapper-Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /MagicMapper.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MagicMapper-Example/Pods-MagicMapper-Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_MagicMapper_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_MagicMapper_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | target 'MagicMapper-Example' do 5 | use_frameworks! 6 | pod 'Alamofire' 7 | pod 'AlamofireImage' 8 | pod 'MagicMapper', :path => "." 9 | end 10 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MagicMapper-Example/Pods-MagicMapper-Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double Pods_MagicMapper_ExampleVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char Pods_MagicMapper_ExampleVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /MagicMapper.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /MagicMapper/Int+Mappable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Adrian Mateoaea on 04/10/2016. 3 | // Copyright © 2016 Magic Mapper. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | extension Int: Mappable { 9 | 10 | public init?(from: Any) { 11 | if let value = from as? Int { 12 | self.init(value) 13 | return 14 | } else if let value = from as? String { 15 | self.init(value) 16 | return 17 | } 18 | 19 | self.init() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MagicMapper/Double+Mappable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Adrian Mateoaea on 04/10/2016. 3 | // Copyright © 2016 Magic Mapper. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | extension Double: Mappable { 9 | 10 | public init?(from: Any) { 11 | if let value = from as? Int { 12 | self.init(value) 13 | return 14 | } else if let value = from as? String { 15 | self.init(value) 16 | return 17 | } 18 | 19 | self.init() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Alamofire.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Alamofire 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MagicMapper/MagicMapper.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/MagicMapper 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (4.0.1) 3 | - AlamofireImage (3.1.0): 4 | - Alamofire (~> 4.0) 5 | - MagicMapper (1.0.2) 6 | 7 | DEPENDENCIES: 8 | - Alamofire 9 | - AlamofireImage 10 | - MagicMapper (from `.`) 11 | 12 | EXTERNAL SOURCES: 13 | MagicMapper: 14 | :path: "." 15 | 16 | SPEC CHECKSUMS: 17 | Alamofire: 7682d43245de14874acd142ec137b144aa1dd335 18 | AlamofireImage: bb8c8351c51cb1633bb6be69b6dbbaff37ce65b7 19 | MagicMapper: 1909d0e15b7a3ef7faec2c5e30791eed0815e934 20 | 21 | PODFILE CHECKSUM: 71624a03031d77812dae9c5583aeca51b145a59d 22 | 23 | COCOAPODS: 1.1.0.rc.2 24 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (4.0.1) 3 | - AlamofireImage (3.1.0): 4 | - Alamofire (~> 4.0) 5 | - MagicMapper (1.0.2) 6 | 7 | DEPENDENCIES: 8 | - Alamofire 9 | - AlamofireImage 10 | - MagicMapper (from `.`) 11 | 12 | EXTERNAL SOURCES: 13 | MagicMapper: 14 | :path: "." 15 | 16 | SPEC CHECKSUMS: 17 | Alamofire: 7682d43245de14874acd142ec137b144aa1dd335 18 | AlamofireImage: bb8c8351c51cb1633bb6be69b6dbbaff37ce65b7 19 | MagicMapper: 1909d0e15b7a3ef7faec2c5e30791eed0815e934 20 | 21 | PODFILE CHECKSUM: 71624a03031d77812dae9c5583aeca51b145a59d 22 | 23 | COCOAPODS: 1.1.0.rc.2 24 | -------------------------------------------------------------------------------- /MagicMapper/String+Mappable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Adrian Mateoaea on 04/10/2016. 3 | // Copyright © 2016 Magic Mapper. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | extension String: Mappable { 9 | 10 | public init?(from: Any) { 11 | if let value = from as? String { 12 | self.init(value) 13 | return 14 | } else if let value = from as? Int { 15 | self.init(value) 16 | return 17 | } else if let value = from as? Double { 18 | self.init(value) 19 | return 20 | } 21 | 22 | self.init() 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MagicMapper/Dictionary+Mappable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Adrian Mateoaea on 04/10/2016. 3 | // Copyright © 2016 Magic Mapper. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | extension Dictionary: Mappable { 9 | 10 | public init?(from: Any) { 11 | self.init() 12 | 13 | guard let dictionary = from as? [Key: Any], let type = Value.self as? Mappable.Type else { 14 | return 15 | } 16 | 17 | for (key, value) in dictionary { 18 | if let element = type.init(from: value) as? Value { 19 | self[key] = element 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Pods/Target Support Files/AlamofireImage/AlamofireImage.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/AlamofireImage 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Alamofire" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 5 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 6 | PODS_BUILD_DIR = $BUILD_DIR 7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_ROOT = ${SRCROOT} 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | -------------------------------------------------------------------------------- /MagicMapper/Bool+Mappable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Adrian Mateoaea on 04/10/2016. 3 | // Copyright © 2016 Magic Mapper. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | extension Bool: Mappable { 9 | 10 | public init?(from: Any) { 11 | if let value = from as? Bool { 12 | self.init(value) 13 | return 14 | } else if let value = from as? Int, value != 0 { 15 | self.init(true) 16 | return 17 | } else if let value = from as? String { 18 | self.init(value.lowercased() == "true") 19 | return 20 | } 21 | 22 | self.init() 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MagicMapper/Array+Mappable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Adrian Mateoaea on 04/10/2016. 3 | // Copyright © 2016 Magic Mapper. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | extension Array: Mappable { 9 | 10 | public init?(from: Any) { 11 | guard let array = from as? [Any], let type = Element.self as? Mappable.Type else { 12 | self.init() 13 | return 14 | } 15 | 16 | let values = array.flatMap { type.init(from: $0) as? Element } 17 | self.init(values) 18 | } 19 | 20 | public var dictionaryValue: Any { 21 | return flatMap { ($0 as? Mappable)?.dictionaryValue } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MagicMapper.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "MagicMapper" 4 | s.version = "1.0.2" 5 | s.summary = "Automatic JSON to model mapper" 6 | s.homepage = "https://github.com/adrianitech/magic-mapper-swift" 7 | s.license = { :type => "Apache License 2.0", :file => "LICENSE" } 8 | s.author = { "Adrian Mateoaea" => "adrianitech@gmail.com" } 9 | 10 | s.ios.deployment_target = '9.0' 11 | s.osx.deployment_target = '10.9' 12 | s.watchos.deployment_target = '2.2' 13 | 14 | s.source = { :git => "https://github.com/adrianitech/magic-mapper-swift.git", :tag => "#{s.version}" } 15 | s.source_files = "MagicMapper", "MagicMapper/*.swift" 16 | 17 | end 18 | -------------------------------------------------------------------------------- /Pods/Local Podspecs/MagicMapper.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MagicMapper", 3 | "version": "1.0.2", 4 | "summary": "Automatic JSON to model mapper", 5 | "homepage": "https://github.com/adrianitech/magic-mapper-swift", 6 | "license": { 7 | "type": "Apache License 2.0", 8 | "file": "LICENSE" 9 | }, 10 | "authors": { 11 | "Adrian Mateoaea": "adrianitech@gmail.com" 12 | }, 13 | "platforms": { 14 | "ios": "9.0", 15 | "osx": "10.9", 16 | "watchos": "2.2" 17 | }, 18 | "source": { 19 | "git": "https://github.com/adrianitech/magic-mapper-swift.git", 20 | "tag": "1.0.2" 21 | }, 22 | "source_files": [ 23 | "MagicMapper", 24 | "MagicMapper/*.swift" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /MagicMapper-Example/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /MagicMapper/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Alamofire/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 4.0.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/MagicMapper/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.2 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/AlamofireImage/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 3.1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MagicMapper-Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MagicMapper-Example/Pods-MagicMapper-Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Alamofire" "$PODS_CONFIGURATION_BUILD_DIR/AlamofireImage" "$PODS_CONFIGURATION_BUILD_DIR/MagicMapper" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Alamofire/Alamofire.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/AlamofireImage/AlamofireImage.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/MagicMapper/MagicMapper.framework/Headers" 7 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "AlamofireImage" -framework "MagicMapper" 8 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 9 | PODS_BUILD_DIR = $BUILD_DIR 10 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MagicMapper-Example/Pods-MagicMapper-Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Alamofire" "$PODS_CONFIGURATION_BUILD_DIR/AlamofireImage" "$PODS_CONFIGURATION_BUILD_DIR/MagicMapper" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 6 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Alamofire/Alamofire.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/AlamofireImage/AlamofireImage.framework/Headers" -iquote "$PODS_CONFIGURATION_BUILD_DIR/MagicMapper/MagicMapper.framework/Headers" 7 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "AlamofireImage" -framework "MagicMapper" 8 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 9 | PODS_BUILD_DIR = $BUILD_DIR 10 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Pods/Alamofire/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Pods/AlamofireImage/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /MagicMapper/Dictionary+Value.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Adrian Mateoaea on 03/10/2016. 3 | // Copyright © 2016 MagicMapper. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | extension Dictionary { 9 | 10 | public func valueForKeyPath(_ keyPath: String) -> Any? { 11 | var keys = keyPath.components(separatedBy: ".") 12 | guard let key = keys.removeFirst() as? Key else { 13 | print("Unable to use string as key on type: \(Key.self)") 14 | return nil 15 | } 16 | 17 | guard var value = self[key] else { return nil } 18 | 19 | if !keys.isEmpty { 20 | while 21 | let key = keys.first, 22 | let index = Int(key), 23 | let arr = value as? [Value], 24 | index >= 0 && index < arr.count { 25 | value = arr[index] 26 | keys.remove(at: 0) 27 | } 28 | if let dict = value as? Dictionary { 29 | let rejoined = keys.joined(separator: ".") 30 | return dict.valueForKeyPath(rejoined) 31 | } 32 | } 33 | 34 | return value 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MagicMapper-Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Pods/AlamofireImage/Source/Image.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Image.swift 3 | // 4 | // Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | #if os(iOS) || os(tvOS) || os(watchOS) 28 | import UIKit 29 | public typealias Image = UIImage 30 | #elseif os(macOS) 31 | import Cocoa 32 | public typealias Image = NSImage 33 | #endif 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | -------------------------------------------------------------------------------- /MagicMapper-Example/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/DispatchQueue+Alamofire.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DispatchQueue+Alamofire.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Dispatch 26 | import Foundation 27 | 28 | extension DispatchQueue { 29 | static var userInteractive: DispatchQueue { return DispatchQueue.global(qos: .userInteractive) } 30 | static var userInitiated: DispatchQueue { return DispatchQueue.global(qos: .userInitiated) } 31 | static var utility: DispatchQueue { return DispatchQueue.global(qos: .utility) } 32 | static var background: DispatchQueue { return DispatchQueue.global(qos: .background) } 33 | 34 | func after(_ delay: TimeInterval, execute closure: @escaping () -> Void) { 35 | asyncAfter(deadline: .now() + delay, execute: closure) 36 | } 37 | 38 | func syncResult(_ closure: () -> T) -> T { 39 | var result: T! 40 | sync { result = closure() } 41 | return result 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /MagicMapper-Example/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // MagicMapper-Example 4 | // 5 | // Created by Adrian Mateoaea on 04/10/2016. 6 | // Copyright © 2016 Magic Mapper. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /Pods/AlamofireImage/Source/AFIError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AFIError.swift 3 | // 4 | // Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | /// `AFIError` is the error type returned by AlamofireImage. 28 | /// 29 | /// - requestCancelled: The request was explicitly cancelled. 30 | /// - imageSerializationFailed: Response data could not be serialized into an image. 31 | public enum AFIError: Error { 32 | case requestCancelled 33 | case imageSerializationFailed 34 | } 35 | 36 | // MARK: - Error Booleans 37 | 38 | extension AFIError { 39 | /// Returns `true` if the `AFIError` is a request cancellation error, `false` otherwise. 40 | public var isRequestCancelledError: Bool { 41 | if case .requestCancelled = self { return true } 42 | return false 43 | } 44 | 45 | /// Returns `true` if the `AFIError` is an image serialization error, `false` otherwise. 46 | public var isImageSerializationFailedError: Bool { 47 | if case .imageSerializationFailed = self { return true } 48 | return false 49 | } 50 | } 51 | 52 | // MARK: - Error Descriptions 53 | 54 | extension AFIError: LocalizedError { 55 | public var errorDescription: String? { 56 | switch self { 57 | case .requestCancelled: 58 | return "The request was explicitly cancelled." 59 | case .imageSerializationFailed: 60 | return "Response data could not be serialized into an image." 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Notifications.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Notifications.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | extension Notification.Name { 28 | /// Used as a namespace for all `URLSessionTask` related notifications. 29 | public struct Task { 30 | /// Posted when a `URLSessionTask` is resumed. The notification `object` contains the resumed `URLSessionTask`. 31 | public static let DidResume = Notification.Name(rawValue: "org.alamofire.notification.name.task.didResume") 32 | 33 | /// Posted when a `URLSessionTask` is suspended. The notification `object` contains the suspended `URLSessionTask`. 34 | public static let DidSuspend = Notification.Name(rawValue: "org.alamofire.notification.name.task.didSuspend") 35 | 36 | /// Posted when a `URLSessionTask` is cancelled. The notification `object` contains the cancelled `URLSessionTask`. 37 | public static let DidCancel = Notification.Name(rawValue: "org.alamofire.notification.name.task.didCancel") 38 | 39 | /// Posted when a `URLSessionTask` is completed. The notification `object` contains the completed `URLSessionTask`. 40 | public static let DidComplete = Notification.Name(rawValue: "org.alamofire.notification.name.task.didComplete") 41 | } 42 | } 43 | 44 | // MARK: - 45 | 46 | extension Notification { 47 | /// Used as a namespace for all `Notification` user info dictionary keys. 48 | public struct Key { 49 | /// User info dictionary key representing the `URLSessionTask` associated with the notification. 50 | public static let Task = "org.alamofire.notification.key.task" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /MagicMapper/Mappable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Adrian Mateoaea on 03/10/2016. 3 | // Copyright © 2016 MagicMapper. All rights reserved. 4 | // 5 | 6 | import Foundation 7 | 8 | public typealias KeyValue = [String: Any] 9 | 10 | public protocol Mappable { 11 | init?(from: Any) 12 | var mapFromDictionary: [String: String] { get } 13 | var mapFromDictionaryTypes: [String: Mappable.Type] { get } 14 | var dictionaryValue: Any { get } 15 | } 16 | 17 | public extension Mappable { 18 | 19 | var mapFromDictionary: [String: String] { 20 | return [:] 21 | } 22 | 23 | var mapFromDictionaryTypes: [String: Mappable.Type] { 24 | return [:] 25 | } 26 | 27 | var dictionaryValue: Any { 28 | return self 29 | } 30 | } 31 | 32 | public extension Mappable where Self: NSObject { 33 | 34 | fileprivate func unwrap(_ any: Any) -> Any? { 35 | let mirror = Mirror(reflecting: any) 36 | 37 | if mirror.displayStyle != .optional { return any } 38 | guard let child = mirror.children.first else { return nil } 39 | 40 | return child.value 41 | } 42 | 43 | init?(from: Any) { 44 | guard let dictionary = from as? KeyValue else { 45 | self.init() 46 | return 47 | } 48 | self.init(dictionary) 49 | } 50 | 51 | init(_ dictionary: KeyValue) { 52 | self.init() 53 | 54 | let properties = Mirror(reflecting: self).children.filter { $0.label != nil } 55 | 56 | for property in properties { 57 | let classKey = property.label! 58 | let dictKey = mapFromDictionary[classKey] ?? classKey 59 | guard let value = dictionary.valueForKeyPath(dictKey) else { continue } 60 | 61 | let mirror = Mirror(reflecting: property.value) 62 | 63 | if let type = mapFromDictionaryTypes[classKey] { 64 | if let valueToBeSet = type.init(from: value) { 65 | self.setValue(valueToBeSet, forKey: classKey) 66 | } 67 | } else if let type = mirror.subjectType as? Mappable.Type { 68 | if let valueToBeSet = type.init(from: value) { 69 | self.setValue(valueToBeSet, forKey: classKey) 70 | } 71 | } else if mirror.displayStyle == .optional { 72 | // Try to set value based on the dictionary type 73 | if let value = value as? Mappable { 74 | self.setValue(value, forKey: classKey) 75 | } 76 | } 77 | } 78 | } 79 | 80 | var dictionaryValue: Any { 81 | return self.dictionary 82 | } 83 | 84 | var dictionary: KeyValue { 85 | var result = KeyValue() 86 | let properties = Mirror(reflecting: self).children.filter { $0.label != nil } 87 | 88 | for property in properties { 89 | let key = property.label! 90 | if let type = unwrap(property.value) as? Mappable { 91 | result[key] = type.dictionaryValue 92 | } 93 | } 94 | 95 | return result 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # magic-mapper-swift 2 | 🌟 Super light and easy automatic JSON to model mapper 3 | 4 | ![](https://img.shields.io/cocoapods/p/MagicMapper.svg) 5 | ![](https://img.shields.io/cocoapods/v/MagicMapper.svg) 6 | ![](https://img.shields.io/cocoapods/l/MagicMapper.svg) 7 | 8 | - [ ] Finish writing `README.md` 9 | - [ ] Ability to map `NSManagedObject` 10 | - [x] Ability to convert model back to dictionary 11 | 12 | ## How to setup 13 | 14 | ### Step 1: Get the JSON model 15 | 16 | ```json 17 | { 18 | "total_count": 176552, 19 | "incomplete_results": false, 20 | "items": [ 21 | {...} 22 | ] 23 | } 24 | ``` 25 | 26 | ### Step 2: Write the Swift models 27 | 28 | ```swift 29 | class GithubRepository: NSObject, Mappable { 30 | var id : String = "" 31 | var name : String = "" 32 | var body : String = "" 33 | var url : String = "" 34 | var photo : String = "" 35 | var createdAt : Date? 36 | } 37 | 38 | class GithubSearch: NSObject, Mappable { 39 | var total : Int = 0 40 | var items : [GithubRepository] = [] 41 | } 42 | ``` 43 | 44 | ### Step 3: Link your custom namings with the JSON model 45 | 46 | The `mapFromDictionary` property lets you customize the properties mappings. You can also access nested values within dictionaries and arrays (example: `emails.0.address`). 47 | 48 | ```swift 49 | var mapFromDictionary: [String : String] { 50 | return [ 51 | "body" : "description", 52 | "photo" : "owner.avatar_url", 53 | "createdAt" : "created_at" 54 | ] 55 | } 56 | ``` 57 | 58 | ### Step 4: Custom properties 59 | 60 | The `mapFromDictionaryTypes` property let's you customize the type of the JSON property (only for optionals). If you have other Swift structures that you need to use, just extend them using the `Mappable` protocol. 61 | 62 | ```swift 63 | var mapFromDictionaryTypes: [String : Mappable.Type] { 64 | return [ 65 | "createdAt" : Date.self 66 | ] 67 | } 68 | ``` 69 | 70 | For instance `createdAt` is of type `Date` and the JSON property is of type `String`. In order to convert the `String` to a `Date` type, just extend it using the `Mappable` protocol and it will automatically know to convert and set the value to the model. 71 | 72 | ```swift 73 | extension Date: Mappable { 74 | 75 | init?(from: Any) { 76 | if let value = from as? String { 77 | let formatter = DateFormatter() 78 | formatter.dateFormat = "YYYY-MM-dd'T'HH':'mm':'ss'Z'" 79 | if let date = formatter.date(from: value) { 80 | self.init(timeIntervalSince1970: date.timeIntervalSince1970) 81 | return 82 | } 83 | } 84 | 85 | self.init() 86 | } 87 | } 88 | ``` 89 | 90 | ### And that's it! 91 | 92 | You can now populate your model from the generic dictionary that comes from your network layer. Happy coding :) 93 | 94 | ```swift 95 | Alamofire.request(APIURL).responseJSON { (response) in 96 | if let dictionary = response.result.value as? KeyValue { 97 | self.feed = GithubSearch(dictionary) 98 | } 99 | } 100 | ``` 101 | 102 | ## Contributing 103 | 104 | There's still work to do here! Our goal is to speed up development times, making JSON mapping easy as 1-2-3. We would love to see you involved in this project! 105 | -------------------------------------------------------------------------------- /MagicMapper-Example/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Result.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Result.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | /// Used to represent whether a request was successful or encountered an error. 28 | /// 29 | /// - success: The request and all post processing operations were successful resulting in the serialization of the 30 | /// provided associated value. 31 | /// 32 | /// - failure: The request encountered an error resulting in a failure. The associated values are the original data 33 | /// provided by the server as well as the error that caused the failure. 34 | public enum Result { 35 | case success(Value) 36 | case failure(Error) 37 | 38 | /// Returns `true` if the result is a success, `false` otherwise. 39 | public var isSuccess: Bool { 40 | switch self { 41 | case .success: 42 | return true 43 | case .failure: 44 | return false 45 | } 46 | } 47 | 48 | /// Returns `true` if the result is a failure, `false` otherwise. 49 | public var isFailure: Bool { 50 | return !isSuccess 51 | } 52 | 53 | /// Returns the associated value if the result is a success, `nil` otherwise. 54 | public var value: Value? { 55 | switch self { 56 | case .success(let value): 57 | return value 58 | case .failure: 59 | return nil 60 | } 61 | } 62 | 63 | /// Returns the associated error value if the result is a failure, `nil` otherwise. 64 | public var error: Error? { 65 | switch self { 66 | case .success: 67 | return nil 68 | case .failure(let error): 69 | return error 70 | } 71 | } 72 | } 73 | 74 | // MARK: - CustomStringConvertible 75 | 76 | extension Result: CustomStringConvertible { 77 | /// The textual representation used when written to an output stream, which includes whether the result was a 78 | /// success or failure. 79 | public var description: String { 80 | switch self { 81 | case .success: 82 | return "SUCCESS" 83 | case .failure: 84 | return "FAILURE" 85 | } 86 | } 87 | } 88 | 89 | // MARK: - CustomDebugStringConvertible 90 | 91 | extension Result: CustomDebugStringConvertible { 92 | /// The debug textual representation used when written to an output stream, which includes whether the result was a 93 | /// success or failure in addition to the value or error. 94 | public var debugDescription: String { 95 | switch self { 96 | case .success(let value): 97 | return "SUCCESS: \(value)" 98 | case .failure(let error): 99 | return "FAILURE: \(error)" 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MagicMapper-Example/Pods-MagicMapper-Example-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | 86 | if [[ "$CONFIGURATION" == "Debug" ]]; then 87 | install_framework "$BUILT_PRODUCTS_DIR/Alamofire/Alamofire.framework" 88 | install_framework "$BUILT_PRODUCTS_DIR/AlamofireImage/AlamofireImage.framework" 89 | install_framework "$BUILT_PRODUCTS_DIR/MagicMapper/MagicMapper.framework" 90 | fi 91 | if [[ "$CONFIGURATION" == "Release" ]]; then 92 | install_framework "$BUILT_PRODUCTS_DIR/Alamofire/Alamofire.framework" 93 | install_framework "$BUILT_PRODUCTS_DIR/AlamofireImage/AlamofireImage.framework" 94 | install_framework "$BUILT_PRODUCTS_DIR/MagicMapper/MagicMapper.framework" 95 | fi 96 | -------------------------------------------------------------------------------- /MagicMapper-Example/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // MagicMapper-Example 4 | // 5 | // Created by Adrian Mateoaea on 04/10/2016. 6 | // Copyright © 2016 Magic Mapper. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Alamofire 11 | import AlamofireImage 12 | import MagicMapper 13 | 14 | extension Date: Mappable { 15 | 16 | public init?(from: Any) { 17 | if let value = from as? String { 18 | let formatter = DateFormatter() 19 | formatter.dateFormat = "YYYY-MM-dd'T'HH':'mm':'ss'Z'" 20 | if let date = formatter.date(from: value) { 21 | self.init(timeIntervalSince1970: date.timeIntervalSince1970) 22 | return 23 | } 24 | } 25 | 26 | self.init() 27 | } 28 | 29 | public var dictionaryValue: Any { 30 | let formatter = DateFormatter() 31 | formatter.dateFormat = "YYYY-MM-dd'T'HH':'mm':'ss'Z'" 32 | return formatter.string(from: self) 33 | } 34 | } 35 | 36 | extension URL: Mappable { 37 | 38 | public init?(from: Any) { 39 | if let value = from as? String { 40 | self.init(string: value) 41 | return 42 | } 43 | 44 | self.init(string: "") 45 | } 46 | 47 | public var dictionaryValue: Any? { 48 | return absoluteString 49 | } 50 | } 51 | 52 | class GithubRepository: NSObject, Mappable { 53 | 54 | var id : String = "" 55 | var name : String = "" 56 | var body : String = "" 57 | var photo : String = "" 58 | var url : URL? 59 | var createdAt : Date? 60 | 61 | var mapFromDictionary: [String : String] { 62 | return [ 63 | "body" : "description", 64 | "photo" : "owner.avatar_url", 65 | "createdAt" : "created_at" 66 | ] 67 | } 68 | 69 | var mapFromDictionaryTypes: [String : Mappable.Type] { 70 | return [ 71 | "url" : URL.self, 72 | "createdAt" : Date.self 73 | ] 74 | } 75 | } 76 | 77 | class GithubSearch: NSObject, Mappable { 78 | 79 | var total : Int = 0 80 | var items : [GithubRepository] = [] 81 | 82 | var mapFromDictionary: [String : String] { 83 | return [ 84 | "total" : "total_count", 85 | ] 86 | } 87 | } 88 | 89 | class ViewController: UITableViewController { 90 | 91 | fileprivate let API = "https://api.github.com/search/repositories?q=+language:swift" 92 | 93 | var feed: GithubSearch? { 94 | didSet { 95 | if let feed = feed { 96 | self.title = "Total: \(feed.total)" 97 | tableView.reloadData() 98 | } 99 | } 100 | } 101 | 102 | override func viewDidLoad() { 103 | super.viewDidLoad() 104 | 105 | Alamofire.request(API).responseJSON { (response) in 106 | if let dictionary = response.result.value as? KeyValue { 107 | self.feed = GithubSearch(dictionary) 108 | print(self.feed?.dictionary) 109 | } 110 | } 111 | } 112 | 113 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 114 | return feed?.items.count ?? 0 115 | } 116 | 117 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 118 | let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell") 119 | cell.tag = indexPath.row 120 | 121 | if let item = feed?.items[indexPath.row] { 122 | Alamofire.request(item.photo).responseImage(completionHandler: { (response) in 123 | DispatchQueue.main.async { [weak cell] in 124 | if let image = response.result.value, cell?.tag == indexPath.row { 125 | cell?.imageView?.image = image 126 | cell?.setNeedsLayout() 127 | } 128 | } 129 | }) 130 | cell.textLabel?.text = item.name 131 | cell.detailTextLabel?.text = item.body 132 | } 133 | 134 | return cell 135 | } 136 | 137 | override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 138 | return 60 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MagicMapper-Example/Pods-MagicMapper-Example-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | realpath() { 27 | DIRECTORY="$(cd "${1%/*}" && pwd)" 28 | FILENAME="${1##*/}" 29 | echo "$DIRECTORY/$FILENAME" 30 | } 31 | 32 | install_resource() 33 | { 34 | if [[ "$1" = /* ]] ; then 35 | RESOURCE_PATH="$1" 36 | else 37 | RESOURCE_PATH="${PODS_ROOT}/$1" 38 | fi 39 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 40 | cat << EOM 41 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 42 | EOM 43 | exit 1 44 | fi 45 | case $RESOURCE_PATH in 46 | *.storyboard) 47 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 48 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 49 | ;; 50 | *.xib) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.framework) 55 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 56 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 57 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 58 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 59 | ;; 60 | *.xcdatamodel) 61 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 62 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 63 | ;; 64 | *.xcdatamodeld) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 67 | ;; 68 | *.xcmappingmodel) 69 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 70 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 71 | ;; 72 | *.xcassets) 73 | ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") 74 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 75 | ;; 76 | *) 77 | echo "$RESOURCE_PATH" 78 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 79 | ;; 80 | esac 81 | } 82 | 83 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 85 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 86 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 87 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | fi 89 | rm -f "$RESOURCES_TO_COPY" 90 | 91 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 92 | then 93 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 94 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 95 | while read line; do 96 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 97 | XCASSET_FILES+=("$line") 98 | fi 99 | done <<<"$OTHER_XCASSETS" 100 | 101 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 102 | fi 103 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Timeline.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Timeline.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | /// Responsible for computing the timing metrics for the complete lifecycle of a `Request`. 28 | public struct Timeline { 29 | /// The time the request was initialized. 30 | public let requestStartTime: CFAbsoluteTime 31 | 32 | /// The time the first bytes were received from or sent to the server. 33 | public let initialResponseTime: CFAbsoluteTime 34 | 35 | /// The time when the request was completed. 36 | public let requestCompletedTime: CFAbsoluteTime 37 | 38 | /// The time when the response serialization was completed. 39 | public let serializationCompletedTime: CFAbsoluteTime 40 | 41 | /// The time interval in seconds from the time the request started to the initial response from the server. 42 | public let latency: TimeInterval 43 | 44 | /// The time interval in seconds from the time the request started to the time the request completed. 45 | public let requestDuration: TimeInterval 46 | 47 | /// The time interval in seconds from the time the request completed to the time response serialization completed. 48 | public let serializationDuration: TimeInterval 49 | 50 | /// The time interval in seconds from the time the request started to the time response serialization completed. 51 | public let totalDuration: TimeInterval 52 | 53 | /// Creates a new `Timeline` instance with the specified request times. 54 | /// 55 | /// - parameter requestStartTime: The time the request was initialized. Defaults to `0.0`. 56 | /// - parameter initialResponseTime: The time the first bytes were received from or sent to the server. 57 | /// Defaults to `0.0`. 58 | /// - parameter requestCompletedTime: The time when the request was completed. Defaults to `0.0`. 59 | /// - parameter serializationCompletedTime: The time when the response serialization was completed. Defaults 60 | /// to `0.0`. 61 | /// 62 | /// - returns: The new `Timeline` instance. 63 | public init( 64 | requestStartTime: CFAbsoluteTime = 0.0, 65 | initialResponseTime: CFAbsoluteTime = 0.0, 66 | requestCompletedTime: CFAbsoluteTime = 0.0, 67 | serializationCompletedTime: CFAbsoluteTime = 0.0) 68 | { 69 | self.requestStartTime = requestStartTime 70 | self.initialResponseTime = initialResponseTime 71 | self.requestCompletedTime = requestCompletedTime 72 | self.serializationCompletedTime = serializationCompletedTime 73 | 74 | self.latency = initialResponseTime - requestStartTime 75 | self.requestDuration = requestCompletedTime - requestStartTime 76 | self.serializationDuration = serializationCompletedTime - requestCompletedTime 77 | self.totalDuration = serializationCompletedTime - requestStartTime 78 | } 79 | } 80 | 81 | // MARK: - CustomStringConvertible 82 | 83 | extension Timeline: CustomStringConvertible { 84 | /// The textual representation used when written to an output stream, which includes the latency, the request 85 | /// duration and the total duration. 86 | public var description: String { 87 | let latency = String(format: "%.3f", self.latency) 88 | let requestDuration = String(format: "%.3f", self.requestDuration) 89 | let serializationDuration = String(format: "%.3f", self.serializationDuration) 90 | let totalDuration = String(format: "%.3f", self.totalDuration) 91 | 92 | // NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is 93 | // fixed, we should move back to string interpolation by reverting commit 7d4a43b1. 94 | let timings = [ 95 | "\"Latency\": " + latency + " secs", 96 | "\"Request Duration\": " + requestDuration + " secs", 97 | "\"Serialization Duration\": " + serializationDuration + " secs", 98 | "\"Total Duration\": " + totalDuration + " secs" 99 | ] 100 | 101 | return "Timeline: { " + timings.joined(separator: ", ") + " }" 102 | } 103 | } 104 | 105 | // MARK: - CustomDebugStringConvertible 106 | 107 | extension Timeline: CustomDebugStringConvertible { 108 | /// The textual representation used when written to an output stream, which includes the request start time, the 109 | /// initial response time, the request completed time, the serialization completed time, the latency, the request 110 | /// duration and the total duration. 111 | public var debugDescription: String { 112 | let requestStartTime = String(format: "%.3f", self.requestStartTime) 113 | let initialResponseTime = String(format: "%.3f", self.initialResponseTime) 114 | let requestCompletedTime = String(format: "%.3f", self.requestCompletedTime) 115 | let serializationCompletedTime = String(format: "%.3f", self.serializationCompletedTime) 116 | let latency = String(format: "%.3f", self.latency) 117 | let requestDuration = String(format: "%.3f", self.requestDuration) 118 | let serializationDuration = String(format: "%.3f", self.serializationDuration) 119 | let totalDuration = String(format: "%.3f", self.totalDuration) 120 | 121 | // NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is 122 | // fixed, we should move back to string interpolation by reverting commit 7d4a43b1. 123 | let timings = [ 124 | "\"Request Start Time\": " + requestStartTime, 125 | "\"Initial Response Time\": " + initialResponseTime, 126 | "\"Request Completed Time\": " + requestCompletedTime, 127 | "\"Serialization Completed Time\": " + serializationCompletedTime, 128 | "\"Latency\": " + latency + " secs", 129 | "\"Request Duration\": " + requestDuration + " secs", 130 | "\"Serialization Duration\": " + serializationDuration + " secs", 131 | "\"Total Duration\": " + totalDuration + " secs" 132 | ] 133 | 134 | return "Timeline: { " + timings.joined(separator: ", ") + " }" 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/NetworkReachabilityManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkReachabilityManager.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | #if !os(watchOS) 26 | 27 | import Foundation 28 | import SystemConfiguration 29 | 30 | /// The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both WWAN and 31 | /// WiFi network interfaces. 32 | /// 33 | /// Reachability can be used to determine background information about why a network operation failed, or to retry 34 | /// network requests when a connection is established. It should not be used to prevent a user from initiating a network 35 | /// request, as it's possible that an initial request may be required to establish reachability. 36 | open class NetworkReachabilityManager { 37 | /** 38 | Defines the various states of network reachability. 39 | 40 | - Unknown: It is unknown whether the network is reachable. 41 | - NotReachable: The network is not reachable. 42 | - ReachableOnWWAN: The network is reachable over the WWAN connection. 43 | - ReachableOnWiFi: The network is reachable over the WiFi connection. 44 | */ 45 | 46 | 47 | /// Defines the various states of network reachability. 48 | /// 49 | /// - unknown: It is unknown whether the network is reachable. 50 | /// - notReachable: The network is not reachable. 51 | /// - reachable: The network is reachable. 52 | public enum NetworkReachabilityStatus { 53 | case unknown 54 | case notReachable 55 | case reachable(ConnectionType) 56 | } 57 | 58 | /// Defines the various connection types detected by reachability flags. 59 | /// 60 | /// - ethernetOrWiFi: The connection type is either over Ethernet or WiFi. 61 | /// - wwan: The connection type is a WWAN connection. 62 | public enum ConnectionType { 63 | case ethernetOrWiFi 64 | case wwan 65 | } 66 | 67 | /// A closure executed when the network reachability status changes. The closure takes a single argument: the 68 | /// network reachability status. 69 | public typealias Listener = (NetworkReachabilityStatus) -> Void 70 | 71 | // MARK: - Properties 72 | 73 | /// Whether the network is currently reachable. 74 | open var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi } 75 | 76 | /// Whether the network is currently reachable over the WWAN interface. 77 | open var isReachableOnWWAN: Bool { return networkReachabilityStatus == .reachable(.wwan) } 78 | 79 | /// Whether the network is currently reachable over Ethernet or WiFi interface. 80 | open var isReachableOnEthernetOrWiFi: Bool { return networkReachabilityStatus == .reachable(.ethernetOrWiFi) } 81 | 82 | /// The current network reachability status. 83 | open var networkReachabilityStatus: NetworkReachabilityStatus { 84 | guard let flags = self.flags else { return .unknown } 85 | return networkReachabilityStatusForFlags(flags) 86 | } 87 | 88 | /// The dispatch queue to execute the `listener` closure on. 89 | open var listenerQueue: DispatchQueue = DispatchQueue.main 90 | 91 | /// A closure executed when the network reachability status changes. 92 | open var listener: Listener? 93 | 94 | private var flags: SCNetworkReachabilityFlags? { 95 | var flags = SCNetworkReachabilityFlags() 96 | 97 | if SCNetworkReachabilityGetFlags(reachability, &flags) { 98 | return flags 99 | } 100 | 101 | return nil 102 | } 103 | 104 | private let reachability: SCNetworkReachability 105 | private var previousFlags: SCNetworkReachabilityFlags 106 | 107 | // MARK: - Initialization 108 | 109 | /// Creates a `NetworkReachabilityManager` instance with the specified host. 110 | /// 111 | /// - parameter host: The host used to evaluate network reachability. 112 | /// 113 | /// - returns: The new `NetworkReachabilityManager` instance. 114 | public convenience init?(host: String) { 115 | guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil } 116 | self.init(reachability: reachability) 117 | } 118 | 119 | /// Creates a `NetworkReachabilityManager` instance that monitors the address 0.0.0.0. 120 | /// 121 | /// Reachability treats the 0.0.0.0 address as a special token that causes it to monitor the general routing 122 | /// status of the device, both IPv4 and IPv6. 123 | /// 124 | /// - returns: The new `NetworkReachabilityManager` instance. 125 | public convenience init?() { 126 | var address = sockaddr_in() 127 | address.sin_len = UInt8(MemoryLayout.size) 128 | address.sin_family = sa_family_t(AF_INET) 129 | 130 | guard let reachability = withUnsafePointer(to: &address, { pointer in 131 | return pointer.withMemoryRebound(to: sockaddr.self, capacity: MemoryLayout.size) { 132 | return SCNetworkReachabilityCreateWithAddress(nil, $0) 133 | } 134 | }) else { return nil } 135 | 136 | self.init(reachability: reachability) 137 | } 138 | 139 | private init(reachability: SCNetworkReachability) { 140 | self.reachability = reachability 141 | self.previousFlags = SCNetworkReachabilityFlags() 142 | } 143 | 144 | deinit { 145 | stopListening() 146 | } 147 | 148 | // MARK: - Listening 149 | 150 | /// Starts listening for changes in network reachability status. 151 | /// 152 | /// - returns: `true` if listening was started successfully, `false` otherwise. 153 | @discardableResult 154 | open func startListening() -> Bool { 155 | var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil) 156 | context.info = Unmanaged.passUnretained(self).toOpaque() 157 | 158 | let callbackEnabled = SCNetworkReachabilitySetCallback( 159 | reachability, 160 | { (_, flags, info) in 161 | let reachability = Unmanaged.fromOpaque(info!).takeUnretainedValue() 162 | reachability.notifyListener(flags) 163 | }, 164 | &context 165 | ) 166 | 167 | let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue) 168 | 169 | listenerQueue.async { 170 | self.previousFlags = SCNetworkReachabilityFlags() 171 | self.notifyListener(self.flags ?? SCNetworkReachabilityFlags()) 172 | } 173 | 174 | return callbackEnabled && queueEnabled 175 | } 176 | 177 | /// Stops listening for changes in network reachability status. 178 | open func stopListening() { 179 | SCNetworkReachabilitySetCallback(reachability, nil, nil) 180 | SCNetworkReachabilitySetDispatchQueue(reachability, nil) 181 | } 182 | 183 | // MARK: - Internal - Listener Notification 184 | 185 | func notifyListener(_ flags: SCNetworkReachabilityFlags) { 186 | guard previousFlags != flags else { return } 187 | previousFlags = flags 188 | 189 | listener?(networkReachabilityStatusForFlags(flags)) 190 | } 191 | 192 | // MARK: - Internal - Network Reachability Status 193 | 194 | func networkReachabilityStatusForFlags(_ flags: SCNetworkReachabilityFlags) -> NetworkReachabilityStatus { 195 | guard flags.contains(.reachable) else { return .notReachable } 196 | 197 | var networkStatus: NetworkReachabilityStatus = .notReachable 198 | 199 | if !flags.contains(.connectionRequired) { networkStatus = .reachable(.ethernetOrWiFi) } 200 | 201 | if flags.contains(.connectionOnDemand) || flags.contains(.connectionOnTraffic) { 202 | if !flags.contains(.interventionRequired) { networkStatus = .reachable(.ethernetOrWiFi) } 203 | } 204 | 205 | #if os(iOS) 206 | if flags.contains(.isWWAN) { networkStatus = .reachable(.wwan) } 207 | #endif 208 | 209 | return networkStatus 210 | } 211 | } 212 | 213 | // MARK: - 214 | 215 | extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {} 216 | 217 | /// Returns whether the two network reachability status values are equal. 218 | /// 219 | /// - parameter lhs: The left-hand side value to compare. 220 | /// - parameter rhs: The right-hand side value to compare. 221 | /// 222 | /// - returns: `true` if the two values are equal, `false` otherwise. 223 | public func ==( 224 | lhs: NetworkReachabilityManager.NetworkReachabilityStatus, 225 | rhs: NetworkReachabilityManager.NetworkReachabilityStatus) 226 | -> Bool 227 | { 228 | switch (lhs, rhs) { 229 | case (.unknown, .unknown): 230 | return true 231 | case (.notReachable, .notReachable): 232 | return true 233 | case let (.reachable(lhsConnectionType), .reachable(rhsConnectionType)): 234 | return lhsConnectionType == rhsConnectionType 235 | default: 236 | return false 237 | } 238 | } 239 | 240 | #endif 241 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Response.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Response.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | /// Used to store all data associated with an non-serialized response of a data or upload request. 28 | public struct DefaultDataResponse { 29 | /// The URL request sent to the server. 30 | public let request: URLRequest? 31 | 32 | /// The server's response to the URL request. 33 | public let response: HTTPURLResponse? 34 | 35 | /// The data returned by the server. 36 | public let data: Data? 37 | 38 | /// The error encountered while executing or validating the request. 39 | public let error: Error? 40 | 41 | var _metrics: AnyObject? 42 | 43 | init(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) { 44 | self.request = request 45 | self.response = response 46 | self.data = data 47 | self.error = error 48 | } 49 | } 50 | 51 | // MARK: - 52 | 53 | /// Used to store all data associated with a serialized response of a data or upload request. 54 | public struct DataResponse { 55 | /// The URL request sent to the server. 56 | public let request: URLRequest? 57 | 58 | /// The server's response to the URL request. 59 | public let response: HTTPURLResponse? 60 | 61 | /// The data returned by the server. 62 | public let data: Data? 63 | 64 | /// The result of response serialization. 65 | public let result: Result 66 | 67 | /// The timeline of the complete lifecycle of the `Request`. 68 | public let timeline: Timeline 69 | 70 | var _metrics: AnyObject? 71 | 72 | /// Creates a `DataResponse` instance with the specified parameters derived from response serialization. 73 | /// 74 | /// - parameter request: The URL request sent to the server. 75 | /// - parameter response: The server's response to the URL request. 76 | /// - parameter data: The data returned by the server. 77 | /// - parameter result: The result of response serialization. 78 | /// - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`. 79 | /// 80 | /// - returns: The new `DataResponse` instance. 81 | public init( 82 | request: URLRequest?, 83 | response: HTTPURLResponse?, 84 | data: Data?, 85 | result: Result, 86 | timeline: Timeline = Timeline()) 87 | { 88 | self.request = request 89 | self.response = response 90 | self.data = data 91 | self.result = result 92 | self.timeline = timeline 93 | } 94 | } 95 | 96 | // MARK: - 97 | 98 | extension DataResponse: CustomStringConvertible, CustomDebugStringConvertible { 99 | /// The textual representation used when written to an output stream, which includes whether the result was a 100 | /// success or failure. 101 | public var description: String { 102 | return result.debugDescription 103 | } 104 | 105 | /// The debug textual representation used when written to an output stream, which includes the URL request, the URL 106 | /// response, the server data, the response serialization result and the timeline. 107 | public var debugDescription: String { 108 | var output: [String] = [] 109 | 110 | output.append(request != nil ? "[Request]: \(request!)" : "[Request]: nil") 111 | output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil") 112 | output.append("[Data]: \(data?.count ?? 0) bytes") 113 | output.append("[Result]: \(result.debugDescription)") 114 | output.append("[Timeline]: \(timeline.debugDescription)") 115 | 116 | return output.joined(separator: "\n") 117 | } 118 | } 119 | 120 | // MARK: - 121 | 122 | /// Used to store all data associated with an non-serialized response of a download request. 123 | public struct DefaultDownloadResponse { 124 | /// The URL request sent to the server. 125 | public let request: URLRequest? 126 | 127 | /// The server's response to the URL request. 128 | public let response: HTTPURLResponse? 129 | 130 | /// The temporary destination URL of the data returned from the server. 131 | public let temporaryURL: URL? 132 | 133 | /// The final destination URL of the data returned from the server if it was moved. 134 | public let destinationURL: URL? 135 | 136 | /// The resume data generated if the request was cancelled. 137 | public let resumeData: Data? 138 | 139 | /// The error encountered while executing or validating the request. 140 | public let error: Error? 141 | 142 | var _metrics: AnyObject? 143 | 144 | init( 145 | request: URLRequest?, 146 | response: HTTPURLResponse?, 147 | temporaryURL: URL?, 148 | destinationURL: URL?, 149 | resumeData: Data?, 150 | error: Error?) 151 | { 152 | self.request = request 153 | self.response = response 154 | self.temporaryURL = temporaryURL 155 | self.destinationURL = destinationURL 156 | self.resumeData = resumeData 157 | self.error = error 158 | } 159 | } 160 | 161 | // MARK: - 162 | 163 | /// Used to store all data associated with a serialized response of a download request. 164 | public struct DownloadResponse { 165 | /// The URL request sent to the server. 166 | public let request: URLRequest? 167 | 168 | /// The server's response to the URL request. 169 | public let response: HTTPURLResponse? 170 | 171 | /// The temporary destination URL of the data returned from the server. 172 | public let temporaryURL: URL? 173 | 174 | /// The final destination URL of the data returned from the server if it was moved. 175 | public let destinationURL: URL? 176 | 177 | /// The resume data generated if the request was cancelled. 178 | public let resumeData: Data? 179 | 180 | /// The result of response serialization. 181 | public let result: Result 182 | 183 | /// The timeline of the complete lifecycle of the request. 184 | public let timeline: Timeline 185 | 186 | var _metrics: AnyObject? 187 | 188 | /// Creates a `DownloadResponse` instance with the specified parameters derived from response serialization. 189 | /// 190 | /// - parameter request: The URL request sent to the server. 191 | /// - parameter response: The server's response to the URL request. 192 | /// - parameter temporaryURL: The temporary destination URL of the data returned from the server. 193 | /// - parameter destinationURL: The final destination URL of the data returned from the server if it was moved. 194 | /// - parameter resumeData: The resume data generated if the request was cancelled. 195 | /// - parameter result: The result of response serialization. 196 | /// - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`. 197 | /// 198 | /// - returns: The new `DownloadResponse` instance. 199 | public init( 200 | request: URLRequest?, 201 | response: HTTPURLResponse?, 202 | temporaryURL: URL?, 203 | destinationURL: URL?, 204 | resumeData: Data?, 205 | result: Result, 206 | timeline: Timeline = Timeline()) 207 | { 208 | self.request = request 209 | self.response = response 210 | self.temporaryURL = temporaryURL 211 | self.destinationURL = destinationURL 212 | self.resumeData = resumeData 213 | self.result = result 214 | self.timeline = timeline 215 | } 216 | } 217 | 218 | // MARK: - 219 | 220 | extension DownloadResponse: CustomStringConvertible, CustomDebugStringConvertible { 221 | /// The textual representation used when written to an output stream, which includes whether the result was a 222 | /// success or failure. 223 | public var description: String { 224 | return result.debugDescription 225 | } 226 | 227 | /// The debug textual representation used when written to an output stream, which includes the URL request, the URL 228 | /// response, the temporary and destination URLs, the resume data, the response serialization result and the 229 | /// timeline. 230 | public var debugDescription: String { 231 | var output: [String] = [] 232 | 233 | output.append(request != nil ? "[Request]: \(request!)" : "[Request]: nil") 234 | output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil") 235 | output.append("[TemporaryURL]: \(temporaryURL?.path ?? "nil")") 236 | output.append("[DestinationURL]: \(destinationURL?.path ?? "nil")") 237 | output.append("[ResumeData]: \(resumeData?.count ?? 0) bytes") 238 | output.append("[Result]: \(result.debugDescription)") 239 | output.append("[Timeline]: \(timeline.debugDescription)") 240 | 241 | return output.joined(separator: "\n") 242 | } 243 | } 244 | 245 | // MARK: - 246 | 247 | protocol Response { 248 | /// The task metrics containing the request / response statistics. 249 | var _metrics: AnyObject? { get set } 250 | mutating func add(_ metrics: AnyObject?) 251 | } 252 | 253 | extension Response { 254 | mutating func add(_ metrics: AnyObject?) { 255 | #if !os(watchOS) 256 | guard #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) else { return } 257 | guard let metrics = metrics as? URLSessionTaskMetrics else { return } 258 | 259 | _metrics = metrics 260 | #endif 261 | } 262 | } 263 | 264 | // MARK: - 265 | 266 | @available(iOS 10.0, macOS 10.12, tvOS 10.0, *) 267 | extension DefaultDataResponse: Response { 268 | #if !os(watchOS) 269 | /// The task metrics containing the request / response statistics. 270 | public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } 271 | #endif 272 | } 273 | 274 | @available(iOS 10.0, macOS 10.12, tvOS 10.0, *) 275 | extension DataResponse: Response { 276 | #if !os(watchOS) 277 | /// The task metrics containing the request / response statistics. 278 | public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } 279 | #endif 280 | } 281 | 282 | @available(iOS 10.0, macOS 10.12, tvOS 10.0, *) 283 | extension DefaultDownloadResponse: Response { 284 | #if !os(watchOS) 285 | /// The task metrics containing the request / response statistics. 286 | public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } 287 | #endif 288 | } 289 | 290 | @available(iOS 10.0, macOS 10.12, tvOS 10.0, *) 291 | extension DownloadResponse: Response { 292 | #if !os(watchOS) 293 | /// The task metrics containing the request / response statistics. 294 | public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } 295 | #endif 296 | } 297 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/Validation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Validation.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | extension Request { 28 | 29 | // MARK: Helper Types 30 | 31 | fileprivate typealias ErrorReason = AFError.ResponseValidationFailureReason 32 | 33 | /// Used to represent whether validation was successful or encountered an error resulting in a failure. 34 | /// 35 | /// - success: The validation was successful. 36 | /// - failure: The validation failed encountering the provided error. 37 | public enum ValidationResult { 38 | case success 39 | case failure(Error) 40 | } 41 | 42 | fileprivate struct MIMEType { 43 | let type: String 44 | let subtype: String 45 | 46 | var isWildcard: Bool { return type == "*" && subtype == "*" } 47 | 48 | init?(_ string: String) { 49 | let components: [String] = { 50 | let stripped = string.trimmingCharacters(in: .whitespacesAndNewlines) 51 | let split = stripped.substring(to: stripped.range(of: ";")?.lowerBound ?? stripped.endIndex) 52 | return split.components(separatedBy: "/") 53 | }() 54 | 55 | if let type = components.first, let subtype = components.last { 56 | self.type = type 57 | self.subtype = subtype 58 | } else { 59 | return nil 60 | } 61 | } 62 | 63 | func matches(_ mime: MIMEType) -> Bool { 64 | switch (type, subtype) { 65 | case (mime.type, mime.subtype), (mime.type, "*"), ("*", mime.subtype), ("*", "*"): 66 | return true 67 | default: 68 | return false 69 | } 70 | } 71 | } 72 | 73 | // MARK: Properties 74 | 75 | fileprivate var acceptableStatusCodes: [Int] { return Array(200..<300) } 76 | 77 | fileprivate var acceptableContentTypes: [String] { 78 | if let accept = request?.value(forHTTPHeaderField: "Accept") { 79 | return accept.components(separatedBy: ",") 80 | } 81 | 82 | return ["*/*"] 83 | } 84 | 85 | // MARK: Status Code 86 | 87 | fileprivate func validate( 88 | statusCode acceptableStatusCodes: S, 89 | response: HTTPURLResponse) 90 | -> ValidationResult 91 | where S.Iterator.Element == Int 92 | { 93 | if acceptableStatusCodes.contains(response.statusCode) { 94 | return .success 95 | } else { 96 | let reason: ErrorReason = .unacceptableStatusCode(code: response.statusCode) 97 | return .failure(AFError.responseValidationFailed(reason: reason)) 98 | } 99 | } 100 | 101 | // MARK: Content Type 102 | 103 | fileprivate func validate( 104 | contentType acceptableContentTypes: S, 105 | response: HTTPURLResponse, 106 | data: Data?) 107 | -> ValidationResult 108 | where S.Iterator.Element == String 109 | { 110 | guard let data = data, data.count > 0 else { return .success } 111 | 112 | guard 113 | let responseContentType = response.mimeType, 114 | let responseMIMEType = MIMEType(responseContentType) 115 | else { 116 | for contentType in acceptableContentTypes { 117 | if let mimeType = MIMEType(contentType), mimeType.isWildcard { 118 | return .success 119 | } 120 | } 121 | 122 | let error: AFError = { 123 | let reason: ErrorReason = .missingContentType(acceptableContentTypes: Array(acceptableContentTypes)) 124 | return AFError.responseValidationFailed(reason: reason) 125 | }() 126 | 127 | return .failure(error) 128 | } 129 | 130 | for contentType in acceptableContentTypes { 131 | if let acceptableMIMEType = MIMEType(contentType), acceptableMIMEType.matches(responseMIMEType) { 132 | return .success 133 | } 134 | } 135 | 136 | let error: AFError = { 137 | let reason: ErrorReason = .unacceptableContentType( 138 | acceptableContentTypes: Array(acceptableContentTypes), 139 | responseContentType: responseContentType 140 | ) 141 | 142 | return AFError.responseValidationFailed(reason: reason) 143 | }() 144 | 145 | return .failure(error) 146 | } 147 | } 148 | 149 | // MARK: - 150 | 151 | extension DataRequest { 152 | /// A closure used to validate a request that takes a URL request, a URL response and data, and returns whether the 153 | /// request was valid. 154 | public typealias Validation = (URLRequest?, HTTPURLResponse, Data?) -> ValidationResult 155 | 156 | /// Validates the request, using the specified closure. 157 | /// 158 | /// If validation fails, subsequent calls to response handlers will have an associated error. 159 | /// 160 | /// - parameter validation: A closure to validate the request. 161 | /// 162 | /// - returns: The request. 163 | @discardableResult 164 | public func validate(_ validation: @escaping Validation) -> Self { 165 | let validationExecution: () -> Void = { [unowned self] in 166 | if 167 | let response = self.response, 168 | self.delegate.error == nil, 169 | case let .failure(error) = validation(self.request, response, self.delegate.data) 170 | { 171 | self.delegate.error = error 172 | } 173 | } 174 | 175 | validations.append(validationExecution) 176 | 177 | return self 178 | } 179 | 180 | /// Validates that the response has a status code in the specified sequence. 181 | /// 182 | /// If validation fails, subsequent calls to response handlers will have an associated error. 183 | /// 184 | /// - parameter range: The range of acceptable status codes. 185 | /// 186 | /// - returns: The request. 187 | @discardableResult 188 | public func validate(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int { 189 | return validate { [unowned self] _, response, _ in 190 | return self.validate(statusCode: acceptableStatusCodes, response: response) 191 | } 192 | } 193 | 194 | /// Validates that the response has a content type in the specified sequence. 195 | /// 196 | /// If validation fails, subsequent calls to response handlers will have an associated error. 197 | /// 198 | /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes. 199 | /// 200 | /// - returns: The request. 201 | @discardableResult 202 | public func validate(contentType acceptableContentTypes: S) -> Self where S.Iterator.Element == String { 203 | return validate { [unowned self] _, response, data in 204 | return self.validate(contentType: acceptableContentTypes, response: response, data: data) 205 | } 206 | } 207 | 208 | /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content 209 | /// type matches any specified in the Accept HTTP header field. 210 | /// 211 | /// If validation fails, subsequent calls to response handlers will have an associated error. 212 | /// 213 | /// - returns: The request. 214 | @discardableResult 215 | public func validate() -> Self { 216 | return validate(statusCode: self.acceptableStatusCodes).validate(contentType: self.acceptableContentTypes) 217 | } 218 | } 219 | 220 | // MARK: - 221 | 222 | extension DownloadRequest { 223 | /// A closure used to validate a request that takes a URL request, a URL response, a temporary URL and a 224 | /// destination URL, and returns whether the request was valid. 225 | public typealias Validation = ( 226 | _ request: URLRequest?, 227 | _ response: HTTPURLResponse, 228 | _ temporaryURL: URL?, 229 | _ destinationURL: URL?) 230 | -> ValidationResult 231 | 232 | /// Validates the request, using the specified closure. 233 | /// 234 | /// If validation fails, subsequent calls to response handlers will have an associated error. 235 | /// 236 | /// - parameter validation: A closure to validate the request. 237 | /// 238 | /// - returns: The request. 239 | @discardableResult 240 | public func validate(_ validation: @escaping Validation) -> Self { 241 | let validationExecution: () -> Void = { [unowned self] in 242 | let request = self.request 243 | let temporaryURL = self.downloadDelegate.temporaryURL 244 | let destinationURL = self.downloadDelegate.destinationURL 245 | 246 | if 247 | let response = self.response, 248 | self.delegate.error == nil, 249 | case let .failure(error) = validation(request, response, temporaryURL, destinationURL) 250 | { 251 | self.delegate.error = error 252 | } 253 | } 254 | 255 | validations.append(validationExecution) 256 | 257 | return self 258 | } 259 | 260 | /// Validates that the response has a status code in the specified sequence. 261 | /// 262 | /// If validation fails, subsequent calls to response handlers will have an associated error. 263 | /// 264 | /// - parameter range: The range of acceptable status codes. 265 | /// 266 | /// - returns: The request. 267 | @discardableResult 268 | public func validate(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int { 269 | return validate { [unowned self] _, response, _, _ in 270 | return self.validate(statusCode: acceptableStatusCodes, response: response) 271 | } 272 | } 273 | 274 | /// Validates that the response has a content type in the specified sequence. 275 | /// 276 | /// If validation fails, subsequent calls to response handlers will have an associated error. 277 | /// 278 | /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes. 279 | /// 280 | /// - returns: The request. 281 | @discardableResult 282 | public func validate(contentType acceptableContentTypes: S) -> Self where S.Iterator.Element == String { 283 | return validate { [unowned self] _, response, _, _ in 284 | let fileURL = self.downloadDelegate.fileURL 285 | 286 | guard let validFileURL = fileURL else { 287 | return .failure(AFError.responseValidationFailed(reason: .dataFileNil)) 288 | } 289 | 290 | do { 291 | let data = try Data(contentsOf: validFileURL) 292 | return self.validate(contentType: acceptableContentTypes, response: response, data: data) 293 | } catch { 294 | return .failure(AFError.responseValidationFailed(reason: .dataFileReadFailed(at: validFileURL))) 295 | } 296 | } 297 | } 298 | 299 | /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content 300 | /// type matches any specified in the Accept HTTP header field. 301 | /// 302 | /// If validation fails, subsequent calls to response handlers will have an associated error. 303 | /// 304 | /// - returns: The request. 305 | @discardableResult 306 | public func validate() -> Self { 307 | return validate(statusCode: self.acceptableStatusCodes).validate(contentType: self.acceptableContentTypes) 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /Pods/AlamofireImage/Source/UIImage+AlamofireImage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+AlamofireImage.swift 3 | // 4 | // Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | #if os(iOS) || os(tvOS) || os(watchOS) 26 | 27 | import CoreGraphics 28 | import Foundation 29 | import UIKit 30 | 31 | // MARK: Initialization 32 | 33 | private let lock = NSLock() 34 | 35 | extension UIImage { 36 | /// Initializes and returns the image object with the specified data in a thread-safe manner. 37 | /// 38 | /// It has been reported that there are thread-safety issues when initializing large amounts of images 39 | /// simultaneously. In the event of these issues occurring, this method can be used in place of 40 | /// the `init?(data:)` method. 41 | /// 42 | /// - parameter data: The data object containing the image data. 43 | /// 44 | /// - returns: An initialized `UIImage` object, or `nil` if the method failed. 45 | public static func af_threadSafeImage(with data: Data) -> UIImage? { 46 | lock.lock() 47 | let image = UIImage(data: data) 48 | lock.unlock() 49 | 50 | return image 51 | } 52 | 53 | /// Initializes and returns the image object with the specified data and scale in a thread-safe manner. 54 | /// 55 | /// It has been reported that there are thread-safety issues when initializing large amounts of images 56 | /// simultaneously. In the event of these issues occurring, this method can be used in place of 57 | /// the `init?(data:scale:)` method. 58 | /// 59 | /// - parameter data: The data object containing the image data. 60 | /// - parameter scale: The scale factor to assume when interpreting the image data. Applying a scale factor of 1.0 61 | /// results in an image whose size matches the pixel-based dimensions of the image. Applying a 62 | /// different scale factor changes the size of the image as reported by the size property. 63 | /// 64 | /// - returns: An initialized `UIImage` object, or `nil` if the method failed. 65 | public static func af_threadSafeImage(with data: Data, scale: CGFloat) -> UIImage? { 66 | lock.lock() 67 | let image = UIImage(data: data, scale: scale) 68 | lock.unlock() 69 | 70 | return image 71 | } 72 | } 73 | 74 | // MARK: - Inflation 75 | 76 | extension UIImage { 77 | private struct AssociatedKey { 78 | static var inflated = "af_UIImage.Inflated" 79 | } 80 | 81 | /// Returns whether the image is inflated. 82 | public var af_inflated: Bool { 83 | get { 84 | if let inflated = objc_getAssociatedObject(self, &AssociatedKey.inflated) as? Bool { 85 | return inflated 86 | } else { 87 | return false 88 | } 89 | } 90 | set { 91 | objc_setAssociatedObject(self, &AssociatedKey.inflated, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 92 | } 93 | } 94 | 95 | /// Inflates the underlying compressed image data to be backed by an uncompressed bitmap representation. 96 | /// 97 | /// Inflating compressed image formats (such as PNG or JPEG) can significantly improve drawing performance as it 98 | /// allows a bitmap representation to be constructed in the background rather than on the main thread. 99 | public func af_inflate() { 100 | guard !af_inflated else { return } 101 | 102 | af_inflated = true 103 | _ = cgImage?.dataProvider?.data 104 | } 105 | } 106 | 107 | // MARK: - Alpha 108 | 109 | extension UIImage { 110 | /// Returns whether the image contains an alpha component. 111 | public var af_containsAlphaComponent: Bool { 112 | let alphaInfo = cgImage?.alphaInfo 113 | 114 | return ( 115 | alphaInfo == .first || 116 | alphaInfo == .last || 117 | alphaInfo == .premultipliedFirst || 118 | alphaInfo == .premultipliedLast 119 | ) 120 | } 121 | 122 | /// Returns whether the image is opaque. 123 | public var af_isOpaque: Bool { return !af_containsAlphaComponent } 124 | } 125 | 126 | // MARK: - Scaling 127 | 128 | extension UIImage { 129 | /// Returns a new version of the image scaled to the specified size. 130 | /// 131 | /// - parameter size: The size to use when scaling the new image. 132 | /// 133 | /// - returns: A new image object. 134 | public func af_imageScaled(to size: CGSize) -> UIImage { 135 | UIGraphicsBeginImageContextWithOptions(size, af_isOpaque, 0.0) 136 | draw(in: CGRect(origin: CGPoint.zero, size: size)) 137 | 138 | let scaledImage = UIGraphicsGetImageFromCurrentImageContext()! 139 | UIGraphicsEndImageContext() 140 | 141 | return scaledImage 142 | } 143 | 144 | /// Returns a new version of the image scaled from the center while maintaining the aspect ratio to fit within 145 | /// a specified size. 146 | /// 147 | /// The resulting image contains an alpha component used to pad the width or height with the necessary transparent 148 | /// pixels to fit the specified size. In high performance critical situations, this may not be the optimal approach. 149 | /// To maintain an opaque image, you could compute the `scaledSize` manually, then use the `af_imageScaledToSize` 150 | /// method in conjunction with a `.Center` content mode to achieve the same visual result. 151 | /// 152 | /// - parameter size: The size to use when scaling the new image. 153 | /// 154 | /// - returns: A new image object. 155 | public func af_imageAspectScaled(toFit size: CGSize) -> UIImage { 156 | let imageAspectRatio = self.size.width / self.size.height 157 | let canvasAspectRatio = size.width / size.height 158 | 159 | var resizeFactor: CGFloat 160 | 161 | if imageAspectRatio > canvasAspectRatio { 162 | resizeFactor = size.width / self.size.width 163 | } else { 164 | resizeFactor = size.height / self.size.height 165 | } 166 | 167 | let scaledSize = CGSize(width: self.size.width * resizeFactor, height: self.size.height * resizeFactor) 168 | let origin = CGPoint(x: (size.width - scaledSize.width) / 2.0, y: (size.height - scaledSize.height) / 2.0) 169 | 170 | UIGraphicsBeginImageContextWithOptions(size, false, 0.0) 171 | draw(in: CGRect(origin: origin, size: scaledSize)) 172 | 173 | let scaledImage = UIGraphicsGetImageFromCurrentImageContext()! 174 | UIGraphicsEndImageContext() 175 | 176 | return scaledImage 177 | } 178 | 179 | /// Returns a new version of the image scaled from the center while maintaining the aspect ratio to fill a 180 | /// specified size. Any pixels that fall outside the specified size are clipped. 181 | /// 182 | /// - parameter size: The size to use when scaling the new image. 183 | /// 184 | /// - returns: A new image object. 185 | public func af_imageAspectScaled(toFill size: CGSize) -> UIImage { 186 | let imageAspectRatio = self.size.width / self.size.height 187 | let canvasAspectRatio = size.width / size.height 188 | 189 | var resizeFactor: CGFloat 190 | 191 | if imageAspectRatio > canvasAspectRatio { 192 | resizeFactor = size.height / self.size.height 193 | } else { 194 | resizeFactor = size.width / self.size.width 195 | } 196 | 197 | let scaledSize = CGSize(width: self.size.width * resizeFactor, height: self.size.height * resizeFactor) 198 | let origin = CGPoint(x: (size.width - scaledSize.width) / 2.0, y: (size.height - scaledSize.height) / 2.0) 199 | 200 | UIGraphicsBeginImageContextWithOptions(size, af_isOpaque, 0.0) 201 | draw(in: CGRect(origin: origin, size: scaledSize)) 202 | 203 | let scaledImage = UIGraphicsGetImageFromCurrentImageContext()! 204 | UIGraphicsEndImageContext() 205 | 206 | return scaledImage 207 | } 208 | } 209 | 210 | // MARK: - Rounded Corners 211 | 212 | extension UIImage { 213 | /// Returns a new version of the image with the corners rounded to the specified radius. 214 | /// 215 | /// - parameter radius: The radius to use when rounding the new image. 216 | /// - parameter divideRadiusByImageScale: Whether to divide the radius by the image scale. Set to `true` when the 217 | /// image has the same resolution for all screen scales such as @1x, @2x and 218 | /// @3x (i.e. single image from web server). Set to `false` for images loaded 219 | /// from an asset catalog with varying resolutions for each screen scale. 220 | /// `false` by default. 221 | /// 222 | /// - returns: A new image object. 223 | public func af_imageRounded(withCornerRadius radius: CGFloat, divideRadiusByImageScale: Bool = false) -> UIImage { 224 | UIGraphicsBeginImageContextWithOptions(size, false, 0.0) 225 | 226 | let scaledRadius = divideRadiusByImageScale ? radius / scale : radius 227 | 228 | let clippingPath = UIBezierPath(roundedRect: CGRect(origin: CGPoint.zero, size: size), cornerRadius: scaledRadius) 229 | clippingPath.addClip() 230 | 231 | draw(in: CGRect(origin: CGPoint.zero, size: size)) 232 | 233 | let roundedImage = UIGraphicsGetImageFromCurrentImageContext()! 234 | UIGraphicsEndImageContext() 235 | 236 | return roundedImage 237 | } 238 | 239 | /// Returns a new version of the image rounded into a circle. 240 | /// 241 | /// - returns: A new image object. 242 | public func af_imageRoundedIntoCircle() -> UIImage { 243 | let radius = min(size.width, size.height) / 2.0 244 | var squareImage = self 245 | 246 | if size.width != size.height { 247 | let squareDimension = min(size.width, size.height) 248 | let squareSize = CGSize(width: squareDimension, height: squareDimension) 249 | squareImage = af_imageAspectScaled(toFill: squareSize) 250 | } 251 | 252 | UIGraphicsBeginImageContextWithOptions(squareImage.size, false, 0.0) 253 | 254 | let clippingPath = UIBezierPath( 255 | roundedRect: CGRect(origin: CGPoint.zero, size: squareImage.size), 256 | cornerRadius: radius 257 | ) 258 | 259 | clippingPath.addClip() 260 | 261 | squareImage.draw(in: CGRect(origin: CGPoint.zero, size: squareImage.size)) 262 | 263 | let roundedImage = UIGraphicsGetImageFromCurrentImageContext()! 264 | UIGraphicsEndImageContext() 265 | 266 | return roundedImage 267 | } 268 | } 269 | 270 | #endif 271 | 272 | #if os(iOS) || os(tvOS) 273 | 274 | import CoreImage 275 | 276 | // MARK: - Core Image Filters 277 | 278 | extension UIImage { 279 | /// Returns a new version of the image using a CoreImage filter with the specified name and parameters. 280 | /// 281 | /// - parameter name: The name of the CoreImage filter to use on the new image. 282 | /// - parameter parameters: The parameters to apply to the CoreImage filter. 283 | /// 284 | /// - returns: A new image object, or `nil` if the filter failed for any reason. 285 | public func af_imageFiltered(withCoreImageFilter name: String, parameters: [String: Any]? = nil) -> UIImage? { 286 | var image: CoreImage.CIImage? = ciImage 287 | 288 | if image == nil, let CGImage = self.cgImage { 289 | image = CoreImage.CIImage(cgImage: CGImage) 290 | } 291 | 292 | guard let coreImage = image else { return nil } 293 | 294 | let context = CIContext(options: [kCIContextPriorityRequestLow: true]) 295 | 296 | var parameters: [String: Any] = parameters ?? [:] 297 | parameters[kCIInputImageKey] = coreImage 298 | 299 | guard let filter = CIFilter(name: name, withInputParameters: parameters) else { return nil } 300 | guard let outputImage = filter.outputImage else { return nil } 301 | 302 | let cgImageRef = context.createCGImage(outputImage, from: outputImage.extent) 303 | 304 | return UIImage(cgImage: cgImageRef!, scale: scale, orientation: imageOrientation) 305 | } 306 | } 307 | 308 | #endif 309 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/ServerTrustPolicy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ServerTrustPolicy.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | /// Responsible for managing the mapping of `ServerTrustPolicy` objects to a given host. 28 | open class ServerTrustPolicyManager { 29 | /// The dictionary of policies mapped to a particular host. 30 | open let policies: [String: ServerTrustPolicy] 31 | 32 | /// Initializes the `ServerTrustPolicyManager` instance with the given policies. 33 | /// 34 | /// Since different servers and web services can have different leaf certificates, intermediate and even root 35 | /// certficates, it is important to have the flexibility to specify evaluation policies on a per host basis. This 36 | /// allows for scenarios such as using default evaluation for host1, certificate pinning for host2, public key 37 | /// pinning for host3 and disabling evaluation for host4. 38 | /// 39 | /// - parameter policies: A dictionary of all policies mapped to a particular host. 40 | /// 41 | /// - returns: The new `ServerTrustPolicyManager` instance. 42 | public init(policies: [String: ServerTrustPolicy]) { 43 | self.policies = policies 44 | } 45 | 46 | /// Returns the `ServerTrustPolicy` for the given host if applicable. 47 | /// 48 | /// By default, this method will return the policy that perfectly matches the given host. Subclasses could override 49 | /// this method and implement more complex mapping implementations such as wildcards. 50 | /// 51 | /// - parameter host: The host to use when searching for a matching policy. 52 | /// 53 | /// - returns: The server trust policy for the given host if found. 54 | open func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? { 55 | return policies[host] 56 | } 57 | } 58 | 59 | // MARK: - 60 | 61 | extension URLSession { 62 | private struct AssociatedKeys { 63 | static var managerKey = "URLSession.ServerTrustPolicyManager" 64 | } 65 | 66 | var serverTrustPolicyManager: ServerTrustPolicyManager? { 67 | get { 68 | return objc_getAssociatedObject(self, &AssociatedKeys.managerKey) as? ServerTrustPolicyManager 69 | } 70 | set (manager) { 71 | objc_setAssociatedObject(self, &AssociatedKeys.managerKey, manager, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 72 | } 73 | } 74 | } 75 | 76 | // MARK: - ServerTrustPolicy 77 | 78 | /// The `ServerTrustPolicy` evaluates the server trust generally provided by an `NSURLAuthenticationChallenge` when 79 | /// connecting to a server over a secure HTTPS connection. The policy configuration then evaluates the server trust 80 | /// with a given set of criteria to determine whether the server trust is valid and the connection should be made. 81 | /// 82 | /// Using pinned certificates or public keys for evaluation helps prevent man-in-the-middle (MITM) attacks and other 83 | /// vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged 84 | /// to route all communication over an HTTPS connection with pinning enabled. 85 | /// 86 | /// - performDefaultEvaluation: Uses the default server trust evaluation while allowing you to control whether to 87 | /// validate the host provided by the challenge. Applications are encouraged to always 88 | /// validate the host in production environments to guarantee the validity of the server's 89 | /// certificate chain. 90 | /// 91 | /// - pinCertificates: Uses the pinned certificates to validate the server trust. The server trust is 92 | /// considered valid if one of the pinned certificates match one of the server certificates. 93 | /// By validating both the certificate chain and host, certificate pinning provides a very 94 | /// secure form of server trust validation mitigating most, if not all, MITM attacks. 95 | /// Applications are encouraged to always validate the host and require a valid certificate 96 | /// chain in production environments. 97 | /// 98 | /// - pinPublicKeys: Uses the pinned public keys to validate the server trust. The server trust is considered 99 | /// valid if one of the pinned public keys match one of the server certificate public keys. 100 | /// By validating both the certificate chain and host, public key pinning provides a very 101 | /// secure form of server trust validation mitigating most, if not all, MITM attacks. 102 | /// Applications are encouraged to always validate the host and require a valid certificate 103 | /// chain in production environments. 104 | /// 105 | /// - disableEvaluation: Disables all evaluation which in turn will always consider any server trust as valid. 106 | /// 107 | /// - customEvaluation: Uses the associated closure to evaluate the validity of the server trust. 108 | public enum ServerTrustPolicy { 109 | case performDefaultEvaluation(validateHost: Bool) 110 | case pinCertificates(certificates: [SecCertificate], validateCertificateChain: Bool, validateHost: Bool) 111 | case pinPublicKeys(publicKeys: [SecKey], validateCertificateChain: Bool, validateHost: Bool) 112 | case disableEvaluation 113 | case customEvaluation((_ serverTrust: SecTrust, _ host: String) -> Bool) 114 | 115 | // MARK: - Bundle Location 116 | 117 | /// Returns all certificates within the given bundle with a `.cer` file extension. 118 | /// 119 | /// - parameter bundle: The bundle to search for all `.cer` files. 120 | /// 121 | /// - returns: All certificates within the given bundle. 122 | public static func certificates(in bundle: Bundle = Bundle.main) -> [SecCertificate] { 123 | var certificates: [SecCertificate] = [] 124 | 125 | let paths = Set([".cer", ".CER", ".crt", ".CRT", ".der", ".DER"].map { fileExtension in 126 | bundle.paths(forResourcesOfType: fileExtension, inDirectory: nil) 127 | }.joined()) 128 | 129 | for path in paths { 130 | if 131 | let certificateData = try? Data(contentsOf: URL(fileURLWithPath: path)) as CFData, 132 | let certificate = SecCertificateCreateWithData(nil, certificateData) 133 | { 134 | certificates.append(certificate) 135 | } 136 | } 137 | 138 | return certificates 139 | } 140 | 141 | /// Returns all public keys within the given bundle with a `.cer` file extension. 142 | /// 143 | /// - parameter bundle: The bundle to search for all `*.cer` files. 144 | /// 145 | /// - returns: All public keys within the given bundle. 146 | public static func publicKeys(in bundle: Bundle = Bundle.main) -> [SecKey] { 147 | var publicKeys: [SecKey] = [] 148 | 149 | for certificate in certificates(in: bundle) { 150 | if let publicKey = publicKey(for: certificate) { 151 | publicKeys.append(publicKey) 152 | } 153 | } 154 | 155 | return publicKeys 156 | } 157 | 158 | // MARK: - Evaluation 159 | 160 | /// Evaluates whether the server trust is valid for the given host. 161 | /// 162 | /// - parameter serverTrust: The server trust to evaluate. 163 | /// - parameter host: The host of the challenge protection space. 164 | /// 165 | /// - returns: Whether the server trust is valid. 166 | public func evaluate(_ serverTrust: SecTrust, forHost host: String) -> Bool { 167 | var serverTrustIsValid = false 168 | 169 | switch self { 170 | case let .performDefaultEvaluation(validateHost): 171 | let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) 172 | SecTrustSetPolicies(serverTrust, policy) 173 | 174 | serverTrustIsValid = trustIsValid(serverTrust) 175 | case let .pinCertificates(pinnedCertificates, validateCertificateChain, validateHost): 176 | if validateCertificateChain { 177 | let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) 178 | SecTrustSetPolicies(serverTrust, policy) 179 | 180 | SecTrustSetAnchorCertificates(serverTrust, pinnedCertificates as CFArray) 181 | SecTrustSetAnchorCertificatesOnly(serverTrust, true) 182 | 183 | serverTrustIsValid = trustIsValid(serverTrust) 184 | } else { 185 | let serverCertificatesDataArray = certificateData(for: serverTrust) 186 | let pinnedCertificatesDataArray = certificateData(for: pinnedCertificates) 187 | 188 | outerLoop: for serverCertificateData in serverCertificatesDataArray { 189 | for pinnedCertificateData in pinnedCertificatesDataArray { 190 | if serverCertificateData == pinnedCertificateData { 191 | serverTrustIsValid = true 192 | break outerLoop 193 | } 194 | } 195 | } 196 | } 197 | case let .pinPublicKeys(pinnedPublicKeys, validateCertificateChain, validateHost): 198 | var certificateChainEvaluationPassed = true 199 | 200 | if validateCertificateChain { 201 | let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) 202 | SecTrustSetPolicies(serverTrust, policy) 203 | 204 | certificateChainEvaluationPassed = trustIsValid(serverTrust) 205 | } 206 | 207 | if certificateChainEvaluationPassed { 208 | outerLoop: for serverPublicKey in ServerTrustPolicy.publicKeys(for: serverTrust) as [AnyObject] { 209 | for pinnedPublicKey in pinnedPublicKeys as [AnyObject] { 210 | if serverPublicKey.isEqual(pinnedPublicKey) { 211 | serverTrustIsValid = true 212 | break outerLoop 213 | } 214 | } 215 | } 216 | } 217 | case .disableEvaluation: 218 | serverTrustIsValid = true 219 | case let .customEvaluation(closure): 220 | serverTrustIsValid = closure(serverTrust, host) 221 | } 222 | 223 | return serverTrustIsValid 224 | } 225 | 226 | // MARK: - Private - Trust Validation 227 | 228 | private func trustIsValid(_ trust: SecTrust) -> Bool { 229 | var isValid = false 230 | 231 | var result = SecTrustResultType.invalid 232 | let status = SecTrustEvaluate(trust, &result) 233 | 234 | if status == errSecSuccess { 235 | let unspecified = SecTrustResultType.unspecified 236 | let proceed = SecTrustResultType.proceed 237 | 238 | 239 | isValid = result == unspecified || result == proceed 240 | } 241 | 242 | return isValid 243 | } 244 | 245 | // MARK: - Private - Certificate Data 246 | 247 | private func certificateData(for trust: SecTrust) -> [Data] { 248 | var certificates: [SecCertificate] = [] 249 | 250 | for index in 0.. [Data] { 260 | return certificates.map { SecCertificateCopyData($0) as Data } 261 | } 262 | 263 | // MARK: - Private - Public Key Extraction 264 | 265 | private static func publicKeys(for trust: SecTrust) -> [SecKey] { 266 | var publicKeys: [SecKey] = [] 267 | 268 | for index in 0.. SecKey? { 281 | var publicKey: SecKey? 282 | 283 | let policy = SecPolicyCreateBasicX509() 284 | var trust: SecTrust? 285 | let trustCreationStatus = SecTrustCreateWithCertificates(certificate, policy, &trust) 286 | 287 | if let trust = trust, trustCreationStatus == errSecSuccess { 288 | publicKey = SecTrustCopyPublicKey(trust) 289 | } 290 | 291 | return publicKey 292 | } 293 | } 294 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MagicMapper-Example/Pods-MagicMapper-Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Alamofire 5 | 6 | Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | 27 | ## AlamofireImage 28 | 29 | Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/) 30 | 31 | Permission is hereby granted, free of charge, to any person obtaining a copy 32 | of this software and associated documentation files (the "Software"), to deal 33 | in the Software without restriction, including without limitation the rights 34 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 35 | copies of the Software, and to permit persons to whom the Software is 36 | furnished to do so, subject to the following conditions: 37 | 38 | The above copyright notice and this permission notice shall be included in 39 | all copies or substantial portions of the Software. 40 | 41 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 46 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 47 | THE SOFTWARE. 48 | 49 | 50 | ## MagicMapper 51 | 52 | Apache License 53 | Version 2.0, January 2004 54 | http://www.apache.org/licenses/ 55 | 56 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 57 | 58 | 1. Definitions. 59 | 60 | "License" shall mean the terms and conditions for use, reproduction, 61 | and distribution as defined by Sections 1 through 9 of this document. 62 | 63 | "Licensor" shall mean the copyright owner or entity authorized by 64 | the copyright owner that is granting the License. 65 | 66 | "Legal Entity" shall mean the union of the acting entity and all 67 | other entities that control, are controlled by, or are under common 68 | control with that entity. For the purposes of this definition, 69 | "control" means (i) the power, direct or indirect, to cause the 70 | direction or management of such entity, whether by contract or 71 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 72 | outstanding shares, or (iii) beneficial ownership of such entity. 73 | 74 | "You" (or "Your") shall mean an individual or Legal Entity 75 | exercising permissions granted by this License. 76 | 77 | "Source" form shall mean the preferred form for making modifications, 78 | including but not limited to software source code, documentation 79 | source, and configuration files. 80 | 81 | "Object" form shall mean any form resulting from mechanical 82 | transformation or translation of a Source form, including but 83 | not limited to compiled object code, generated documentation, 84 | and conversions to other media types. 85 | 86 | "Work" shall mean the work of authorship, whether in Source or 87 | Object form, made available under the License, as indicated by a 88 | copyright notice that is included in or attached to the work 89 | (an example is provided in the Appendix below). 90 | 91 | "Derivative Works" shall mean any work, whether in Source or Object 92 | form, that is based on (or derived from) the Work and for which the 93 | editorial revisions, annotations, elaborations, or other modifications 94 | represent, as a whole, an original work of authorship. For the purposes 95 | of this License, Derivative Works shall not include works that remain 96 | separable from, or merely link (or bind by name) to the interfaces of, 97 | the Work and Derivative Works thereof. 98 | 99 | "Contribution" shall mean any work of authorship, including 100 | the original version of the Work and any modifications or additions 101 | to that Work or Derivative Works thereof, that is intentionally 102 | submitted to Licensor for inclusion in the Work by the copyright owner 103 | or by an individual or Legal Entity authorized to submit on behalf of 104 | the copyright owner. For the purposes of this definition, "submitted" 105 | means any form of electronic, verbal, or written communication sent 106 | to the Licensor or its representatives, including but not limited to 107 | communication on electronic mailing lists, source code control systems, 108 | and issue tracking systems that are managed by, or on behalf of, the 109 | Licensor for the purpose of discussing and improving the Work, but 110 | excluding communication that is conspicuously marked or otherwise 111 | designated in writing by the copyright owner as "Not a Contribution." 112 | 113 | "Contributor" shall mean Licensor and any individual or Legal Entity 114 | on behalf of whom a Contribution has been received by Licensor and 115 | subsequently incorporated within the Work. 116 | 117 | 2. Grant of Copyright License. Subject to the terms and conditions of 118 | this License, each Contributor hereby grants to You a perpetual, 119 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 120 | copyright license to reproduce, prepare Derivative Works of, 121 | publicly display, publicly perform, sublicense, and distribute the 122 | Work and such Derivative Works in Source or Object form. 123 | 124 | 3. Grant of Patent License. Subject to the terms and conditions of 125 | this License, each Contributor hereby grants to You a perpetual, 126 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 127 | (except as stated in this section) patent license to make, have made, 128 | use, offer to sell, sell, import, and otherwise transfer the Work, 129 | where such license applies only to those patent claims licensable 130 | by such Contributor that are necessarily infringed by their 131 | Contribution(s) alone or by combination of their Contribution(s) 132 | with the Work to which such Contribution(s) was submitted. If You 133 | institute patent litigation against any entity (including a 134 | cross-claim or counterclaim in a lawsuit) alleging that the Work 135 | or a Contribution incorporated within the Work constitutes direct 136 | or contributory patent infringement, then any patent licenses 137 | granted to You under this License for that Work shall terminate 138 | as of the date such litigation is filed. 139 | 140 | 4. Redistribution. You may reproduce and distribute copies of the 141 | Work or Derivative Works thereof in any medium, with or without 142 | modifications, and in Source or Object form, provided that You 143 | meet the following conditions: 144 | 145 | (a) You must give any other recipients of the Work or 146 | Derivative Works a copy of this License; and 147 | 148 | (b) You must cause any modified files to carry prominent notices 149 | stating that You changed the files; and 150 | 151 | (c) You must retain, in the Source form of any Derivative Works 152 | that You distribute, all copyright, patent, trademark, and 153 | attribution notices from the Source form of the Work, 154 | excluding those notices that do not pertain to any part of 155 | the Derivative Works; and 156 | 157 | (d) If the Work includes a "NOTICE" text file as part of its 158 | distribution, then any Derivative Works that You distribute must 159 | include a readable copy of the attribution notices contained 160 | within such NOTICE file, excluding those notices that do not 161 | pertain to any part of the Derivative Works, in at least one 162 | of the following places: within a NOTICE text file distributed 163 | as part of the Derivative Works; within the Source form or 164 | documentation, if provided along with the Derivative Works; or, 165 | within a display generated by the Derivative Works, if and 166 | wherever such third-party notices normally appear. The contents 167 | of the NOTICE file are for informational purposes only and 168 | do not modify the License. You may add Your own attribution 169 | notices within Derivative Works that You distribute, alongside 170 | or as an addendum to the NOTICE text from the Work, provided 171 | that such additional attribution notices cannot be construed 172 | as modifying the License. 173 | 174 | You may add Your own copyright statement to Your modifications and 175 | may provide additional or different license terms and conditions 176 | for use, reproduction, or distribution of Your modifications, or 177 | for any such Derivative Works as a whole, provided Your use, 178 | reproduction, and distribution of the Work otherwise complies with 179 | the conditions stated in this License. 180 | 181 | 5. Submission of Contributions. Unless You explicitly state otherwise, 182 | any Contribution intentionally submitted for inclusion in the Work 183 | by You to the Licensor shall be under the terms and conditions of 184 | this License, without any additional terms or conditions. 185 | Notwithstanding the above, nothing herein shall supersede or modify 186 | the terms of any separate license agreement you may have executed 187 | with Licensor regarding such Contributions. 188 | 189 | 6. Trademarks. This License does not grant permission to use the trade 190 | names, trademarks, service marks, or product names of the Licensor, 191 | except as required for reasonable and customary use in describing the 192 | origin of the Work and reproducing the content of the NOTICE file. 193 | 194 | 7. Disclaimer of Warranty. Unless required by applicable law or 195 | agreed to in writing, Licensor provides the Work (and each 196 | Contributor provides its Contributions) on an "AS IS" BASIS, 197 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 198 | implied, including, without limitation, any warranties or conditions 199 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 200 | PARTICULAR PURPOSE. You are solely responsible for determining the 201 | appropriateness of using or redistributing the Work and assume any 202 | risks associated with Your exercise of permissions under this License. 203 | 204 | 8. Limitation of Liability. In no event and under no legal theory, 205 | whether in tort (including negligence), contract, or otherwise, 206 | unless required by applicable law (such as deliberate and grossly 207 | negligent acts) or agreed to in writing, shall any Contributor be 208 | liable to You for damages, including any direct, indirect, special, 209 | incidental, or consequential damages of any character arising as a 210 | result of this License or out of the use or inability to use the 211 | Work (including but not limited to damages for loss of goodwill, 212 | work stoppage, computer failure or malfunction, or any and all 213 | other commercial damages or losses), even if such Contributor 214 | has been advised of the possibility of such damages. 215 | 216 | 9. Accepting Warranty or Additional Liability. While redistributing 217 | the Work or Derivative Works thereof, You may choose to offer, 218 | and charge a fee for, acceptance of support, warranty, indemnity, 219 | or other liability obligations and/or rights consistent with this 220 | License. However, in accepting such obligations, You may act only 221 | on Your own behalf and on Your sole responsibility, not on behalf 222 | of any other Contributor, and only if You agree to indemnify, 223 | defend, and hold each Contributor harmless for any liability 224 | incurred by, or claims asserted against, such Contributor by reason 225 | of your accepting any such warranty or additional liability. 226 | 227 | END OF TERMS AND CONDITIONS 228 | 229 | APPENDIX: How to apply the Apache License to your work. 230 | 231 | To apply the Apache License to your work, attach the following 232 | boilerplate notice, with the fields enclosed by brackets "{}" 233 | replaced with your own identifying information. (Don't include 234 | the brackets!) The text should be enclosed in the appropriate 235 | comment syntax for the file format. We also recommend that a 236 | file or class name and description of purpose be included on the 237 | same "printed page" as the copyright notice for easier 238 | identification within third-party archives. 239 | 240 | Copyright {yyyy} {name of copyright owner} 241 | 242 | Licensed under the Apache License, Version 2.0 (the "License"); 243 | you may not use this file except in compliance with the License. 244 | You may obtain a copy of the License at 245 | 246 | http://www.apache.org/licenses/LICENSE-2.0 247 | 248 | Unless required by applicable law or agreed to in writing, software 249 | distributed under the License is distributed on an "AS IS" BASIS, 250 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 251 | See the License for the specific language governing permissions and 252 | limitations under the License. 253 | 254 | Generated by CocoaPods - https://cocoapods.org 255 | -------------------------------------------------------------------------------- /Pods/AlamofireImage/Source/ImageCache.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageCache.swift 3 | // 4 | // Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Alamofire 26 | import Foundation 27 | 28 | #if os(iOS) || os(tvOS) || os(watchOS) 29 | import UIKit 30 | #elseif os(macOS) 31 | import Cocoa 32 | #endif 33 | 34 | // MARK: ImageCache 35 | 36 | /// The `ImageCache` protocol defines a set of APIs for adding, removing and fetching images from a cache. 37 | public protocol ImageCache { 38 | /// Adds the image to the cache with the given identifier. 39 | func add(_ image: Image, withIdentifier identifier: String) 40 | 41 | /// Removes the image from the cache matching the given identifier. 42 | func removeImage(withIdentifier identifier: String) -> Bool 43 | 44 | /// Removes all images stored in the cache. 45 | @discardableResult 46 | func removeAllImages() -> Bool 47 | 48 | /// Returns the image in the cache associated with the given identifier. 49 | func image(withIdentifier identifier: String) -> Image? 50 | } 51 | 52 | /// The `ImageRequestCache` protocol extends the `ImageCache` protocol by adding methods for adding, removing and 53 | /// fetching images from a cache given an `URLRequest` and additional identifier. 54 | public protocol ImageRequestCache: ImageCache { 55 | /// Adds the image to the cache using an identifier created from the request and identifier. 56 | func add(_ image: Image, for request: URLRequest, withIdentifier identifier: String?) 57 | 58 | /// Removes the image from the cache using an identifier created from the request and identifier. 59 | func removeImage(for request: URLRequest, withIdentifier identifier: String?) -> Bool 60 | 61 | /// Returns the image from the cache associated with an identifier created from the request and identifier. 62 | func image(for request: URLRequest, withIdentifier identifier: String?) -> Image? 63 | } 64 | 65 | // MARK: - 66 | 67 | /// The `AutoPurgingImageCache` in an in-memory image cache used to store images up to a given memory capacity. When 68 | /// the memory capacity is reached, the image cache is sorted by last access date, then the oldest image is continuously 69 | /// purged until the preferred memory usage after purge is met. Each time an image is accessed through the cache, the 70 | /// internal access date of the image is updated. 71 | public class AutoPurgingImageCache: ImageRequestCache { 72 | private class CachedImage { 73 | let image: Image 74 | let identifier: String 75 | let totalBytes: UInt64 76 | var lastAccessDate: Date 77 | 78 | init(_ image: Image, identifier: String) { 79 | self.image = image 80 | self.identifier = identifier 81 | self.lastAccessDate = Date() 82 | 83 | self.totalBytes = { 84 | #if os(iOS) || os(tvOS) || os(watchOS) 85 | let size = CGSize(width: image.size.width * image.scale, height: image.size.height * image.scale) 86 | #elseif os(macOS) 87 | let size = CGSize(width: image.size.width, height: image.size.height) 88 | #endif 89 | 90 | let bytesPerPixel: CGFloat = 4.0 91 | let bytesPerRow = size.width * bytesPerPixel 92 | let totalBytes = UInt64(bytesPerRow) * UInt64(size.height) 93 | 94 | return totalBytes 95 | }() 96 | } 97 | 98 | func accessImage() -> Image { 99 | lastAccessDate = Date() 100 | return image 101 | } 102 | } 103 | 104 | // MARK: Properties 105 | 106 | /// The current total memory usage in bytes of all images stored within the cache. 107 | public var memoryUsage: UInt64 { 108 | var memoryUsage: UInt64 = 0 109 | synchronizationQueue.sync { memoryUsage = self.currentMemoryUsage } 110 | 111 | return memoryUsage 112 | } 113 | 114 | /// The total memory capacity of the cache in bytes. 115 | public let memoryCapacity: UInt64 116 | 117 | /// The preferred memory usage after purge in bytes. During a purge, images will be purged until the memory 118 | /// capacity drops below this limit. 119 | public let preferredMemoryUsageAfterPurge: UInt64 120 | 121 | private let synchronizationQueue: DispatchQueue 122 | private var cachedImages: [String: CachedImage] 123 | private var currentMemoryUsage: UInt64 124 | 125 | // MARK: Initialization 126 | 127 | /// Initialies the `AutoPurgingImageCache` instance with the given memory capacity and preferred memory usage 128 | /// after purge limit. 129 | /// 130 | /// Please note, the memory capacity must always be greater than or equal to the preferred memory usage after purge. 131 | /// 132 | /// - parameter memoryCapacity: The total memory capacity of the cache in bytes. `100 MB` by default. 133 | /// - parameter preferredMemoryUsageAfterPurge: The preferred memory usage after purge in bytes. `60 MB` by default. 134 | /// 135 | /// - returns: The new `AutoPurgingImageCache` instance. 136 | public init(memoryCapacity: UInt64 = 100_000_000, preferredMemoryUsageAfterPurge: UInt64 = 60_000_000) { 137 | self.memoryCapacity = memoryCapacity 138 | self.preferredMemoryUsageAfterPurge = preferredMemoryUsageAfterPurge 139 | 140 | precondition( 141 | memoryCapacity >= preferredMemoryUsageAfterPurge, 142 | "The `memoryCapacity` must be greater than or equal to `preferredMemoryUsageAfterPurge`" 143 | ) 144 | 145 | self.cachedImages = [:] 146 | self.currentMemoryUsage = 0 147 | 148 | self.synchronizationQueue = { 149 | let name = String(format: "org.alamofire.autopurgingimagecache-%08x%08x", arc4random(), arc4random()) 150 | return DispatchQueue(label: name, attributes: .concurrent) 151 | }() 152 | 153 | #if os(iOS) || os(tvOS) 154 | NotificationCenter.default.addObserver( 155 | self, 156 | selector: #selector(AutoPurgingImageCache.removeAllImages), 157 | name: Notification.Name.UIApplicationDidReceiveMemoryWarning, 158 | object: nil 159 | ) 160 | #endif 161 | } 162 | 163 | deinit { 164 | NotificationCenter.default.removeObserver(self) 165 | } 166 | 167 | // MARK: Add Image to Cache 168 | 169 | /// Adds the image to the cache using an identifier created from the request and optional identifier. 170 | /// 171 | /// - parameter image: The image to add to the cache. 172 | /// - parameter request: The request used to generate the image's unique identifier. 173 | /// - parameter identifier: The additional identifier to append to the image's unique identifier. 174 | public func add(_ image: Image, for request: URLRequest, withIdentifier identifier: String? = nil) { 175 | let requestIdentifier = imageCacheKey(for: request, withIdentifier: identifier) 176 | add(image, withIdentifier: requestIdentifier) 177 | } 178 | 179 | /// Adds the image to the cache with the given identifier. 180 | /// 181 | /// - parameter image: The image to add to the cache. 182 | /// - parameter identifier: The identifier to use to uniquely identify the image. 183 | public func add(_ image: Image, withIdentifier identifier: String) { 184 | synchronizationQueue.async(flags: [.barrier]) { 185 | let cachedImage = CachedImage(image, identifier: identifier) 186 | 187 | if let previousCachedImage = self.cachedImages[identifier] { 188 | self.currentMemoryUsage -= previousCachedImage.totalBytes 189 | } 190 | 191 | self.cachedImages[identifier] = cachedImage 192 | self.currentMemoryUsage += cachedImage.totalBytes 193 | } 194 | 195 | synchronizationQueue.async(flags: [.barrier]) { 196 | if self.currentMemoryUsage > self.memoryCapacity { 197 | let bytesToPurge = self.currentMemoryUsage - self.preferredMemoryUsageAfterPurge 198 | 199 | 200 | var sortedImages = self.cachedImages.map{$1} 201 | sortedImages.sort { 202 | let date1 = $0.lastAccessDate 203 | let date2 = $1.lastAccessDate 204 | 205 | return date1.timeIntervalSince(date2) < 0.0 206 | } 207 | 208 | var bytesPurged = UInt64(0) 209 | 210 | for cachedImage in sortedImages { 211 | self.cachedImages.removeValue(forKey: cachedImage.identifier) 212 | bytesPurged += cachedImage.totalBytes 213 | 214 | if bytesPurged >= bytesToPurge { 215 | break 216 | } 217 | } 218 | 219 | self.currentMemoryUsage -= bytesPurged 220 | } 221 | } 222 | } 223 | 224 | // MARK: Remove Image from Cache 225 | 226 | /// Removes the image from the cache using an identifier created from the request and optional identifier. 227 | /// 228 | /// - parameter request: The request used to generate the image's unique identifier. 229 | /// - parameter identifier: The additional identifier to append to the image's unique identifier. 230 | /// 231 | /// - returns: `true` if the image was removed, `false` otherwise. 232 | @discardableResult 233 | public func removeImage(for request: URLRequest, withIdentifier identifier: String?) -> Bool { 234 | let requestIdentifier = imageCacheKey(for: request, withIdentifier: identifier) 235 | return removeImage(withIdentifier: requestIdentifier) 236 | } 237 | 238 | /// Removes all images from the cache created from the request. 239 | /// 240 | /// - parameter request: The request used to generate the image's unique identifier. 241 | /// 242 | /// - returns: `true` if any images were removed, `false` otherwise. 243 | @discardableResult 244 | public func removeImages(matching request: URLRequest) -> Bool { 245 | let requestIdentifier = imageCacheKey(for: request, withIdentifier: nil) 246 | var removed = false 247 | 248 | synchronizationQueue.sync { 249 | for key in self.cachedImages.keys where key.hasPrefix(requestIdentifier) { 250 | if let cachedImage = self.cachedImages.removeValue(forKey: key) { 251 | self.currentMemoryUsage -= cachedImage.totalBytes 252 | removed = true 253 | } 254 | } 255 | } 256 | 257 | return removed 258 | } 259 | 260 | /// Removes the image from the cache matching the given identifier. 261 | /// 262 | /// - parameter identifier: The unique identifier for the image. 263 | /// 264 | /// - returns: `true` if the image was removed, `false` otherwise. 265 | @discardableResult 266 | public func removeImage(withIdentifier identifier: String) -> Bool { 267 | var removed = false 268 | 269 | synchronizationQueue.sync { 270 | if let cachedImage = self.cachedImages.removeValue(forKey: identifier) { 271 | self.currentMemoryUsage -= cachedImage.totalBytes 272 | removed = true 273 | } 274 | } 275 | 276 | return removed 277 | } 278 | 279 | /// Removes all images stored in the cache. 280 | /// 281 | /// - returns: `true` if images were removed from the cache, `false` otherwise. 282 | @discardableResult 283 | @objc public func removeAllImages() -> Bool { 284 | var removed = false 285 | 286 | synchronizationQueue.sync { 287 | if !self.cachedImages.isEmpty { 288 | self.cachedImages.removeAll() 289 | self.currentMemoryUsage = 0 290 | 291 | removed = true 292 | } 293 | } 294 | 295 | return removed 296 | } 297 | 298 | // MARK: Fetch Image from Cache 299 | 300 | /// Returns the image from the cache associated with an identifier created from the request and optional identifier. 301 | /// 302 | /// - parameter request: The request used to generate the image's unique identifier. 303 | /// - parameter identifier: The additional identifier to append to the image's unique identifier. 304 | /// 305 | /// - returns: The image if it is stored in the cache, `nil` otherwise. 306 | public func image(for request: URLRequest, withIdentifier identifier: String? = nil) -> Image? { 307 | let requestIdentifier = imageCacheKey(for: request, withIdentifier: identifier) 308 | return image(withIdentifier: requestIdentifier) 309 | } 310 | 311 | /// Returns the image in the cache associated with the given identifier. 312 | /// 313 | /// - parameter identifier: The unique identifier for the image. 314 | /// 315 | /// - returns: The image if it is stored in the cache, `nil` otherwise. 316 | public func image(withIdentifier identifier: String) -> Image? { 317 | var image: Image? 318 | 319 | synchronizationQueue.sync { 320 | if let cachedImage = self.cachedImages[identifier] { 321 | image = cachedImage.accessImage() 322 | } 323 | } 324 | 325 | return image 326 | } 327 | 328 | // MARK: Private - Helper Methods 329 | 330 | private func imageCacheKey(for request: URLRequest, withIdentifier identifier: String?) -> String { 331 | var key = request.url?.absoluteString ?? "" 332 | 333 | if let identifier = identifier { 334 | key += "-\(identifier)" 335 | } 336 | 337 | return key 338 | } 339 | } 340 | -------------------------------------------------------------------------------- /Pods/AlamofireImage/Source/Request+AlamofireImage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Request+AlamofireImage.swift 3 | // 4 | // Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Alamofire 26 | import Foundation 27 | 28 | #if os(iOS) || os(tvOS) 29 | import UIKit 30 | #elseif os(watchOS) 31 | import UIKit 32 | import WatchKit 33 | #elseif os(macOS) 34 | import Cocoa 35 | #endif 36 | 37 | extension DataRequest { 38 | static var acceptableImageContentTypes: Set = [ 39 | "image/tiff", 40 | "image/jpeg", 41 | "image/gif", 42 | "image/png", 43 | "image/ico", 44 | "image/x-icon", 45 | "image/bmp", 46 | "image/x-bmp", 47 | "image/x-xbitmap", 48 | "image/x-ms-bmp", 49 | "image/x-win-bitmap" 50 | ] 51 | 52 | static let streamImageInitialBytePattern = Data(bytes: [255, 216]) // 0xffd8 53 | 54 | /// Adds the content types specified to the list of acceptable images content types for validation. 55 | /// 56 | /// - parameter contentTypes: The additional content types. 57 | public class func addAcceptableImageContentTypes(_ contentTypes: Set) { 58 | DataRequest.acceptableImageContentTypes.formUnion(contentTypes) 59 | } 60 | 61 | // MARK: - iOS, tvOS and watchOS 62 | 63 | #if os(iOS) || os(tvOS) || os(watchOS) 64 | 65 | /// Creates a response serializer that returns an image initialized from the response data using the specified 66 | /// image options. 67 | /// 68 | /// - parameter imageScale: The scale factor used when interpreting the image data to construct 69 | /// `responseImage`. Specifying a scale factor of 1.0 results in an image whose 70 | /// size matches the pixel-based dimensions of the image. Applying a different 71 | /// scale factor changes the size of the image as reported by the size property. 72 | /// `Screen.scale` by default. 73 | /// - parameter inflateResponseImage: Whether to automatically inflate response image data for compressed formats 74 | /// (such as PNG or JPEG). Enabling this can significantly improve drawing 75 | /// performance as it allows a bitmap representation to be constructed in the 76 | /// background rather than on the main thread. `true` by default. 77 | /// 78 | /// - returns: An image response serializer. 79 | public class func imageResponseSerializer( 80 | imageScale: CGFloat = DataRequest.imageScale, 81 | inflateResponseImage: Bool = true) 82 | -> DataResponseSerializer 83 | { 84 | return DataResponseSerializer { request, response, data, error in 85 | let result = serializeResponseData(response: response, data: data, error: error) 86 | 87 | guard case let .success(data) = result else { return .failure(result.error!) } 88 | 89 | do { 90 | try DataRequest.validateContentType(for: request, response: response) 91 | 92 | let image = try DataRequest.image(from: data, withImageScale: imageScale) 93 | if inflateResponseImage { image.af_inflate() } 94 | 95 | return .success(image) 96 | } catch { 97 | return .failure(error) 98 | } 99 | } 100 | } 101 | 102 | /// Adds a response handler to be called once the request has finished. 103 | /// 104 | /// - parameter imageScale: The scale factor used when interpreting the image data to construct 105 | /// `responseImage`. Specifying a scale factor of 1.0 results in an image whose 106 | /// size matches the pixel-based dimensions of the image. Applying a different 107 | /// scale factor changes the size of the image as reported by the size property. 108 | /// This is set to the value of scale of the main screen by default, which 109 | /// automatically scales images for retina displays, for instance. 110 | /// `Screen.scale` by default. 111 | /// - parameter inflateResponseImage: Whether to automatically inflate response image data for compressed formats 112 | /// (such as PNG or JPEG). Enabling this can significantly improve drawing 113 | /// performance as it allows a bitmap representation to be constructed in the 114 | /// background rather than on the main thread. `true` by default. 115 | /// - parameter completionHandler: A closure to be executed once the request has finished. The closure takes 4 116 | /// arguments: the URL request, the URL response, if one was received, the image, 117 | /// if one could be created from the URL response and data, and any error produced 118 | /// while creating the image. 119 | /// 120 | /// - returns: The request. 121 | @discardableResult 122 | public func responseImage( 123 | imageScale: CGFloat = DataRequest.imageScale, 124 | inflateResponseImage: Bool = true, 125 | completionHandler: @escaping (DataResponse) -> Void) 126 | -> Self 127 | { 128 | return response( 129 | responseSerializer: DataRequest.imageResponseSerializer( 130 | imageScale: imageScale, 131 | inflateResponseImage: inflateResponseImage 132 | ), 133 | completionHandler: completionHandler 134 | ) 135 | } 136 | 137 | /// Sets a closure to be called periodically during the lifecycle of the request as data is read from the server 138 | /// and converted into images. 139 | /// 140 | /// - parameter imageScale: The scale factor used when interpreting the image data to construct 141 | /// `responseImage`. Specifying a scale factor of 1.0 results in an image whose 142 | /// size matches the pixel-based dimensions of the image. Applying a different 143 | /// scale factor changes the size of the image as reported by the size property. 144 | /// This is set to the value of scale of the main screen by default, which 145 | /// automatically scales images for retina displays, for instance. 146 | /// `Screen.scale` by default. 147 | /// - parameter inflateResponseImage: Whether to automatically inflate response image data for compressed formats 148 | /// (such as PNG or JPEG). Enabling this can significantly improve drawing 149 | /// performance as it allows a bitmap representation to be constructed in the 150 | /// background rather than on the main thread. `true` by default. 151 | /// - parameter completionHandler: A closure to be executed when the request has new image. The closure takes 1 152 | /// argument: the image, if one could be created from the data. 153 | /// 154 | /// - returns: The request. 155 | @discardableResult 156 | public func streamImage( 157 | imageScale: CGFloat = DataRequest.imageScale, 158 | inflateResponseImage: Bool = true, 159 | completionHandler: @escaping (Image) -> Void) 160 | -> Self 161 | { 162 | var imageData = Data() 163 | 164 | return stream { chunkData in 165 | if chunkData.starts(with: DataRequest.streamImageInitialBytePattern) { 166 | imageData = Data() 167 | } 168 | 169 | imageData.append(chunkData) 170 | 171 | if let image = DataRequest.serializeImage(from: imageData) { 172 | completionHandler(image) 173 | } 174 | } 175 | } 176 | 177 | private class func serializeImage( 178 | from data: Data, 179 | imageScale: CGFloat = DataRequest.imageScale, 180 | inflateResponseImage: Bool = true) 181 | -> UIImage? 182 | { 183 | guard data.count > 0 else { return nil } 184 | 185 | do { 186 | let image = try DataRequest.image(from: data, withImageScale: imageScale) 187 | if inflateResponseImage { image.af_inflate() } 188 | 189 | return image 190 | } catch { 191 | return nil 192 | } 193 | } 194 | 195 | private class func image(from data: Data, withImageScale imageScale: CGFloat) throws -> UIImage { 196 | if let image = UIImage.af_threadSafeImage(with: data, scale: imageScale) { 197 | return image 198 | } 199 | 200 | throw AFIError.imageSerializationFailed 201 | } 202 | 203 | private class var imageScale: CGFloat { 204 | #if os(iOS) || os(tvOS) 205 | return UIScreen.main.scale 206 | #elseif os(watchOS) 207 | return WKInterfaceDevice.current().screenScale 208 | #endif 209 | } 210 | 211 | #elseif os(macOS) 212 | 213 | // MARK: - macOS 214 | 215 | /// Creates a response serializer that returns an image initialized from the response data. 216 | /// 217 | /// - returns: An image response serializer. 218 | public class func imageResponseSerializer() -> DataResponseSerializer { 219 | return DataResponseSerializer { request, response, data, error in 220 | let result = serializeResponseData(response: response, data: data, error: error) 221 | 222 | guard case let .success(data) = result else { return .failure(result.error!) } 223 | 224 | do { 225 | try DataRequest.validateContentType(for: request, response: response) 226 | } catch { 227 | return .failure(error) 228 | } 229 | 230 | guard let bitmapImage = NSBitmapImageRep(data: data) else { 231 | return .failure(AFIError.imageSerializationFailed) 232 | } 233 | 234 | let image = NSImage(size: NSSize(width: bitmapImage.pixelsWide, height: bitmapImage.pixelsHigh)) 235 | image.addRepresentation(bitmapImage) 236 | 237 | return .success(image) 238 | } 239 | } 240 | 241 | /// Adds a response handler to be called once the request has finished. 242 | /// 243 | /// - parameter completionHandler: A closure to be executed once the request has finished. The closure takes 4 244 | /// arguments: the URL request, the URL response, if one was received, the image, if 245 | /// one could be created from the URL response and data, and any error produced while 246 | /// creating the image. 247 | /// 248 | /// - returns: The request. 249 | @discardableResult 250 | public func responseImage(completionHandler: @escaping (DataResponse) -> Void) -> Self { 251 | return response( 252 | responseSerializer: DataRequest.imageResponseSerializer(), 253 | completionHandler: completionHandler 254 | ) 255 | } 256 | 257 | /// Sets a closure to be called periodically during the lifecycle of the request as data is read from the server 258 | /// and converted into images. 259 | /// 260 | /// - parameter completionHandler: A closure to be executed when the request has new image. The closure takes 1 261 | /// argument: the image, if one could be created from the data. 262 | /// 263 | /// - returns: The request. 264 | @discardableResult 265 | public func streamImage(completionHandler: @escaping (Image) -> Void) -> Self { 266 | var imageData = Data() 267 | 268 | return stream { chunkData in 269 | if chunkData.starts(with: DataRequest.streamImageInitialBytePattern) { 270 | imageData = Data() 271 | } 272 | 273 | imageData.append(chunkData) 274 | 275 | if let image = DataRequest.serializeImage(from: imageData) { 276 | completionHandler(image) 277 | } 278 | } 279 | } 280 | 281 | private class func serializeImage(from data: Data) -> NSImage? { 282 | guard data.count > 0 else { return nil } 283 | guard let bitmapImage = NSBitmapImageRep(data: data) else { return nil } 284 | 285 | let image = NSImage(size: NSSize(width: bitmapImage.pixelsWide, height: bitmapImage.pixelsHigh)) 286 | image.addRepresentation(bitmapImage) 287 | 288 | return image 289 | } 290 | 291 | #endif 292 | 293 | // MARK: - Private - Shared Helper Methods 294 | 295 | private class func validateContentType(for request: URLRequest?, response: HTTPURLResponse?) throws { 296 | if let url = request?.url, url.isFileURL { return } 297 | 298 | guard let mimeType = response?.mimeType else { 299 | let contentTypes = Array(DataRequest.acceptableImageContentTypes) 300 | throw AFError.responseValidationFailed(reason: .missingContentType(acceptableContentTypes: contentTypes)) 301 | } 302 | 303 | guard DataRequest.acceptableImageContentTypes.contains(mimeType) else { 304 | let contentTypes = Array(DataRequest.acceptableImageContentTypes) 305 | 306 | throw AFError.responseValidationFailed( 307 | reason: .unacceptableContentType(acceptableContentTypes: contentTypes, responseContentType: mimeType) 308 | ) 309 | } 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-MagicMapper-Example/Pods-MagicMapper-Example-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | License 38 | MIT 39 | Title 40 | Alamofire 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Copyright (c) 2015-2016 Alamofire Software Foundation (http://alamofire.org/) 47 | 48 | Permission is hereby granted, free of charge, to any person obtaining a copy 49 | of this software and associated documentation files (the "Software"), to deal 50 | in the Software without restriction, including without limitation the rights 51 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 52 | copies of the Software, and to permit persons to whom the Software is 53 | furnished to do so, subject to the following conditions: 54 | 55 | The above copyright notice and this permission notice shall be included in 56 | all copies or substantial portions of the Software. 57 | 58 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 62 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 63 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 64 | THE SOFTWARE. 65 | 66 | License 67 | MIT 68 | Title 69 | AlamofireImage 70 | Type 71 | PSGroupSpecifier 72 | 73 | 74 | FooterText 75 | Apache License 76 | Version 2.0, January 2004 77 | http://www.apache.org/licenses/ 78 | 79 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 80 | 81 | 1. Definitions. 82 | 83 | "License" shall mean the terms and conditions for use, reproduction, 84 | and distribution as defined by Sections 1 through 9 of this document. 85 | 86 | "Licensor" shall mean the copyright owner or entity authorized by 87 | the copyright owner that is granting the License. 88 | 89 | "Legal Entity" shall mean the union of the acting entity and all 90 | other entities that control, are controlled by, or are under common 91 | control with that entity. For the purposes of this definition, 92 | "control" means (i) the power, direct or indirect, to cause the 93 | direction or management of such entity, whether by contract or 94 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 95 | outstanding shares, or (iii) beneficial ownership of such entity. 96 | 97 | "You" (or "Your") shall mean an individual or Legal Entity 98 | exercising permissions granted by this License. 99 | 100 | "Source" form shall mean the preferred form for making modifications, 101 | including but not limited to software source code, documentation 102 | source, and configuration files. 103 | 104 | "Object" form shall mean any form resulting from mechanical 105 | transformation or translation of a Source form, including but 106 | not limited to compiled object code, generated documentation, 107 | and conversions to other media types. 108 | 109 | "Work" shall mean the work of authorship, whether in Source or 110 | Object form, made available under the License, as indicated by a 111 | copyright notice that is included in or attached to the work 112 | (an example is provided in the Appendix below). 113 | 114 | "Derivative Works" shall mean any work, whether in Source or Object 115 | form, that is based on (or derived from) the Work and for which the 116 | editorial revisions, annotations, elaborations, or other modifications 117 | represent, as a whole, an original work of authorship. For the purposes 118 | of this License, Derivative Works shall not include works that remain 119 | separable from, or merely link (or bind by name) to the interfaces of, 120 | the Work and Derivative Works thereof. 121 | 122 | "Contribution" shall mean any work of authorship, including 123 | the original version of the Work and any modifications or additions 124 | to that Work or Derivative Works thereof, that is intentionally 125 | submitted to Licensor for inclusion in the Work by the copyright owner 126 | or by an individual or Legal Entity authorized to submit on behalf of 127 | the copyright owner. For the purposes of this definition, "submitted" 128 | means any form of electronic, verbal, or written communication sent 129 | to the Licensor or its representatives, including but not limited to 130 | communication on electronic mailing lists, source code control systems, 131 | and issue tracking systems that are managed by, or on behalf of, the 132 | Licensor for the purpose of discussing and improving the Work, but 133 | excluding communication that is conspicuously marked or otherwise 134 | designated in writing by the copyright owner as "Not a Contribution." 135 | 136 | "Contributor" shall mean Licensor and any individual or Legal Entity 137 | on behalf of whom a Contribution has been received by Licensor and 138 | subsequently incorporated within the Work. 139 | 140 | 2. Grant of Copyright License. Subject to the terms and conditions of 141 | this License, each Contributor hereby grants to You a perpetual, 142 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 143 | copyright license to reproduce, prepare Derivative Works of, 144 | publicly display, publicly perform, sublicense, and distribute the 145 | Work and such Derivative Works in Source or Object form. 146 | 147 | 3. Grant of Patent License. Subject to the terms and conditions of 148 | this License, each Contributor hereby grants to You a perpetual, 149 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 150 | (except as stated in this section) patent license to make, have made, 151 | use, offer to sell, sell, import, and otherwise transfer the Work, 152 | where such license applies only to those patent claims licensable 153 | by such Contributor that are necessarily infringed by their 154 | Contribution(s) alone or by combination of their Contribution(s) 155 | with the Work to which such Contribution(s) was submitted. If You 156 | institute patent litigation against any entity (including a 157 | cross-claim or counterclaim in a lawsuit) alleging that the Work 158 | or a Contribution incorporated within the Work constitutes direct 159 | or contributory patent infringement, then any patent licenses 160 | granted to You under this License for that Work shall terminate 161 | as of the date such litigation is filed. 162 | 163 | 4. Redistribution. You may reproduce and distribute copies of the 164 | Work or Derivative Works thereof in any medium, with or without 165 | modifications, and in Source or Object form, provided that You 166 | meet the following conditions: 167 | 168 | (a) You must give any other recipients of the Work or 169 | Derivative Works a copy of this License; and 170 | 171 | (b) You must cause any modified files to carry prominent notices 172 | stating that You changed the files; and 173 | 174 | (c) You must retain, in the Source form of any Derivative Works 175 | that You distribute, all copyright, patent, trademark, and 176 | attribution notices from the Source form of the Work, 177 | excluding those notices that do not pertain to any part of 178 | the Derivative Works; and 179 | 180 | (d) If the Work includes a "NOTICE" text file as part of its 181 | distribution, then any Derivative Works that You distribute must 182 | include a readable copy of the attribution notices contained 183 | within such NOTICE file, excluding those notices that do not 184 | pertain to any part of the Derivative Works, in at least one 185 | of the following places: within a NOTICE text file distributed 186 | as part of the Derivative Works; within the Source form or 187 | documentation, if provided along with the Derivative Works; or, 188 | within a display generated by the Derivative Works, if and 189 | wherever such third-party notices normally appear. The contents 190 | of the NOTICE file are for informational purposes only and 191 | do not modify the License. You may add Your own attribution 192 | notices within Derivative Works that You distribute, alongside 193 | or as an addendum to the NOTICE text from the Work, provided 194 | that such additional attribution notices cannot be construed 195 | as modifying the License. 196 | 197 | You may add Your own copyright statement to Your modifications and 198 | may provide additional or different license terms and conditions 199 | for use, reproduction, or distribution of Your modifications, or 200 | for any such Derivative Works as a whole, provided Your use, 201 | reproduction, and distribution of the Work otherwise complies with 202 | the conditions stated in this License. 203 | 204 | 5. Submission of Contributions. Unless You explicitly state otherwise, 205 | any Contribution intentionally submitted for inclusion in the Work 206 | by You to the Licensor shall be under the terms and conditions of 207 | this License, without any additional terms or conditions. 208 | Notwithstanding the above, nothing herein shall supersede or modify 209 | the terms of any separate license agreement you may have executed 210 | with Licensor regarding such Contributions. 211 | 212 | 6. Trademarks. This License does not grant permission to use the trade 213 | names, trademarks, service marks, or product names of the Licensor, 214 | except as required for reasonable and customary use in describing the 215 | origin of the Work and reproducing the content of the NOTICE file. 216 | 217 | 7. Disclaimer of Warranty. Unless required by applicable law or 218 | agreed to in writing, Licensor provides the Work (and each 219 | Contributor provides its Contributions) on an "AS IS" BASIS, 220 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 221 | implied, including, without limitation, any warranties or conditions 222 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 223 | PARTICULAR PURPOSE. You are solely responsible for determining the 224 | appropriateness of using or redistributing the Work and assume any 225 | risks associated with Your exercise of permissions under this License. 226 | 227 | 8. Limitation of Liability. In no event and under no legal theory, 228 | whether in tort (including negligence), contract, or otherwise, 229 | unless required by applicable law (such as deliberate and grossly 230 | negligent acts) or agreed to in writing, shall any Contributor be 231 | liable to You for damages, including any direct, indirect, special, 232 | incidental, or consequential damages of any character arising as a 233 | result of this License or out of the use or inability to use the 234 | Work (including but not limited to damages for loss of goodwill, 235 | work stoppage, computer failure or malfunction, or any and all 236 | other commercial damages or losses), even if such Contributor 237 | has been advised of the possibility of such damages. 238 | 239 | 9. Accepting Warranty or Additional Liability. While redistributing 240 | the Work or Derivative Works thereof, You may choose to offer, 241 | and charge a fee for, acceptance of support, warranty, indemnity, 242 | or other liability obligations and/or rights consistent with this 243 | License. However, in accepting such obligations, You may act only 244 | on Your own behalf and on Your sole responsibility, not on behalf 245 | of any other Contributor, and only if You agree to indemnify, 246 | defend, and hold each Contributor harmless for any liability 247 | incurred by, or claims asserted against, such Contributor by reason 248 | of your accepting any such warranty or additional liability. 249 | 250 | END OF TERMS AND CONDITIONS 251 | 252 | APPENDIX: How to apply the Apache License to your work. 253 | 254 | To apply the Apache License to your work, attach the following 255 | boilerplate notice, with the fields enclosed by brackets "{}" 256 | replaced with your own identifying information. (Don't include 257 | the brackets!) The text should be enclosed in the appropriate 258 | comment syntax for the file format. We also recommend that a 259 | file or class name and description of purpose be included on the 260 | same "printed page" as the copyright notice for easier 261 | identification within third-party archives. 262 | 263 | Copyright {yyyy} {name of copyright owner} 264 | 265 | Licensed under the Apache License, Version 2.0 (the "License"); 266 | you may not use this file except in compliance with the License. 267 | You may obtain a copy of the License at 268 | 269 | http://www.apache.org/licenses/LICENSE-2.0 270 | 271 | Unless required by applicable law or agreed to in writing, software 272 | distributed under the License is distributed on an "AS IS" BASIS, 273 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 274 | See the License for the specific language governing permissions and 275 | limitations under the License. 276 | 277 | License 278 | Apache License 2.0 279 | Title 280 | MagicMapper 281 | Type 282 | PSGroupSpecifier 283 | 284 | 285 | FooterText 286 | Generated by CocoaPods - https://cocoapods.org 287 | Title 288 | 289 | Type 290 | PSGroupSpecifier 291 | 292 | 293 | StringsTable 294 | Acknowledgements 295 | Title 296 | Acknowledgements 297 | 298 | 299 | -------------------------------------------------------------------------------- /Pods/Alamofire/Source/ParameterEncoding.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParameterEncoding.swift 3 | // 4 | // Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/) 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | // 24 | 25 | import Foundation 26 | 27 | /// HTTP method definitions. 28 | /// 29 | /// See https://tools.ietf.org/html/rfc7231#section-4.3 30 | public enum HTTPMethod: String { 31 | case options = "OPTIONS" 32 | case get = "GET" 33 | case head = "HEAD" 34 | case post = "POST" 35 | case put = "PUT" 36 | case patch = "PATCH" 37 | case delete = "DELETE" 38 | case trace = "TRACE" 39 | case connect = "CONNECT" 40 | } 41 | 42 | // MARK: - 43 | 44 | /// A dictionary of parameters to apply to a `URLRequest`. 45 | public typealias Parameters = [String: Any] 46 | 47 | /// A type used to define how a set of parameters are applied to a `URLRequest`. 48 | public protocol ParameterEncoding { 49 | /// Creates a URL request by encoding parameters and applying them onto an existing request. 50 | /// 51 | /// - parameter urlRequest: The request to have parameters applied. 52 | /// - parameter parameters: The parameters to apply. 53 | /// 54 | /// - throws: An `AFError.parameterEncodingFailed` error if encoding fails. 55 | /// 56 | /// - returns: The encoded request. 57 | func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest 58 | } 59 | 60 | // MARK: - 61 | 62 | /// Creates a url-encoded query string to be set as or appended to any existing URL query string or set as the HTTP 63 | /// body of the URL request. Whether the query string is set or appended to any existing URL query string or set as 64 | /// the HTTP body depends on the destination of the encoding. 65 | /// 66 | /// The `Content-Type` HTTP header field of an encoded request with HTTP body is set to 67 | /// `application/x-www-form-urlencoded; charset=utf-8`. Since there is no published specification for how to encode 68 | /// collection types, the convention of appending `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending 69 | /// the key surrounded by square brackets for nested dictionary values (`foo[bar]=baz`). 70 | public struct URLEncoding: ParameterEncoding { 71 | 72 | // MARK: Helper Types 73 | 74 | /// Defines whether the url-encoded query string is applied to the existing query string or HTTP body of the 75 | /// resulting URL request. 76 | /// 77 | /// - methodDependent: Applies encoded query string result to existing query string for `GET`, `HEAD` and `DELETE` 78 | /// requests and sets as the HTTP body for requests with any other HTTP method. 79 | /// - queryString: Sets or appends encoded query string result to existing query string. 80 | /// - httpBody: Sets encoded query string result as the HTTP body of the URL request. 81 | public enum Destination { 82 | case methodDependent, queryString, httpBody 83 | } 84 | 85 | // MARK: Properties 86 | 87 | /// Returns a default `URLEncoding` instance. 88 | public static var `default`: URLEncoding { return URLEncoding() } 89 | 90 | /// Returns a `URLEncoding` instance with a `.methodDependent` destination. 91 | public static var methodDependent: URLEncoding { return URLEncoding() } 92 | 93 | /// Returns a `URLEncoding` instance with a `.queryString` destination. 94 | public static var queryString: URLEncoding { return URLEncoding(destination: .queryString) } 95 | 96 | /// Returns a `URLEncoding` instance with an `.httpBody` destination. 97 | public static var httpBody: URLEncoding { return URLEncoding(destination: .httpBody) } 98 | 99 | /// The destination defining where the encoded query string is to be applied to the URL request. 100 | public let destination: Destination 101 | 102 | // MARK: Initialization 103 | 104 | /// Creates a `URLEncoding` instance using the specified destination. 105 | /// 106 | /// - parameter destination: The destination defining where the encoded query string is to be applied. 107 | /// 108 | /// - returns: The new `URLEncoding` instance. 109 | public init(destination: Destination = .methodDependent) { 110 | self.destination = destination 111 | } 112 | 113 | // MARK: Encoding 114 | 115 | /// Creates a URL request by encoding parameters and applying them onto an existing request. 116 | /// 117 | /// - parameter urlRequest: The request to have parameters applied. 118 | /// - parameter parameters: The parameters to apply. 119 | /// 120 | /// - throws: An `Error` if the encoding process encounters an error. 121 | /// 122 | /// - returns: The encoded request. 123 | public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { 124 | var urlRequest = try urlRequest.asURLRequest() 125 | 126 | guard let parameters = parameters else { return urlRequest } 127 | 128 | if let method = HTTPMethod(rawValue: urlRequest.httpMethod ?? "GET"), encodesParametersInURL(with: method) { 129 | guard let url = urlRequest.url else { 130 | throw AFError.parameterEncodingFailed(reason: .missingURL) 131 | } 132 | 133 | if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty { 134 | let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters) 135 | urlComponents.percentEncodedQuery = percentEncodedQuery 136 | urlRequest.url = urlComponents.url 137 | } 138 | } else { 139 | if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { 140 | urlRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type") 141 | } 142 | 143 | urlRequest.httpBody = query(parameters).data(using: .utf8, allowLossyConversion: false) 144 | } 145 | 146 | return urlRequest 147 | } 148 | 149 | /// Creates percent-escaped, URL encoded query string components from the given key-value pair using recursion. 150 | /// 151 | /// - parameter key: The key of the query component. 152 | /// - parameter value: The value of the query component. 153 | /// 154 | /// - returns: The percent-escaped, URL encoded query string components. 155 | public func queryComponents(fromKey key: String, value: Any) -> [(String, String)] { 156 | var components: [(String, String)] = [] 157 | 158 | if let dictionary = value as? [String: Any] { 159 | for (nestedKey, value) in dictionary { 160 | components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value) 161 | } 162 | } else if let array = value as? [Any] { 163 | for value in array { 164 | components += queryComponents(fromKey: "\(key)[]", value: value) 165 | } 166 | } else if let value = value as? NSNumber { 167 | if value.isBool { 168 | components.append((escape(key), escape((value.boolValue ? "1" : "0")))) 169 | } else { 170 | components.append((escape(key), escape("\(value)"))) 171 | } 172 | } else if let bool = value as? Bool { 173 | components.append((escape(key), escape((bool ? "1" : "0")))) 174 | } else { 175 | components.append((escape(key), escape("\(value)"))) 176 | } 177 | 178 | return components 179 | } 180 | 181 | /// Returns a percent-escaped string following RFC 3986 for a query string key or value. 182 | /// 183 | /// RFC 3986 states that the following characters are "reserved" characters. 184 | /// 185 | /// - General Delimiters: ":", "#", "[", "]", "@", "?", "/" 186 | /// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "=" 187 | /// 188 | /// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow 189 | /// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/" 190 | /// should be percent-escaped in the query string. 191 | /// 192 | /// - parameter string: The string to be percent-escaped. 193 | /// 194 | /// - returns: The percent-escaped string. 195 | public func escape(_ string: String) -> String { 196 | let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4 197 | let subDelimitersToEncode = "!$&'()*+,;=" 198 | 199 | var allowedCharacterSet = CharacterSet.urlQueryAllowed 200 | allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)") 201 | 202 | return string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string 203 | } 204 | 205 | private func query(_ parameters: [String: Any]) -> String { 206 | var components: [(String, String)] = [] 207 | 208 | for key in parameters.keys.sorted(by: <) { 209 | let value = parameters[key]! 210 | components += queryComponents(fromKey: key, value: value) 211 | } 212 | 213 | return components.map { "\($0)=\($1)" }.joined(separator: "&") 214 | } 215 | 216 | private func encodesParametersInURL(with method: HTTPMethod) -> Bool { 217 | switch destination { 218 | case .queryString: 219 | return true 220 | case .httpBody: 221 | return false 222 | default: 223 | break 224 | } 225 | 226 | switch method { 227 | case .get, .head, .delete: 228 | return true 229 | default: 230 | return false 231 | } 232 | } 233 | } 234 | 235 | // MARK: - 236 | 237 | /// Uses `JSONSerialization` to create a JSON representation of the parameters object, which is set as the body of the 238 | /// request. The `Content-Type` HTTP header field of an encoded request is set to `application/json`. 239 | public struct JSONEncoding: ParameterEncoding { 240 | 241 | // MARK: Properties 242 | 243 | /// Returns a `JSONEncoding` instance with default writing options. 244 | public static var `default`: JSONEncoding { return JSONEncoding() } 245 | 246 | /// Returns a `JSONEncoding` instance with `.prettyPrinted` writing options. 247 | public static var prettyPrinted: JSONEncoding { return JSONEncoding(options: .prettyPrinted) } 248 | 249 | /// The options for writing the parameters as JSON data. 250 | public let options: JSONSerialization.WritingOptions 251 | 252 | // MARK: Initialization 253 | 254 | /// Creates a `JSONEncoding` instance using the specified options. 255 | /// 256 | /// - parameter options: The options for writing the parameters as JSON data. 257 | /// 258 | /// - returns: The new `JSONEncoding` instance. 259 | public init(options: JSONSerialization.WritingOptions = []) { 260 | self.options = options 261 | } 262 | 263 | // MARK: Encoding 264 | 265 | /// Creates a URL request by encoding parameters and applying them onto an existing request. 266 | /// 267 | /// - parameter urlRequest: The request to have parameters applied. 268 | /// - parameter parameters: The parameters to apply. 269 | /// 270 | /// - throws: An `Error` if the encoding process encounters an error. 271 | /// 272 | /// - returns: The encoded request. 273 | public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { 274 | var urlRequest = try urlRequest.asURLRequest() 275 | 276 | guard let parameters = parameters else { return urlRequest } 277 | 278 | do { 279 | let data = try JSONSerialization.data(withJSONObject: parameters, options: options) 280 | 281 | if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { 282 | urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") 283 | } 284 | 285 | urlRequest.httpBody = data 286 | } catch { 287 | throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error)) 288 | } 289 | 290 | return urlRequest 291 | } 292 | } 293 | 294 | // MARK: - 295 | 296 | /// Uses `PropertyListSerialization` to create a plist representation of the parameters object, according to the 297 | /// associated format and write options values, which is set as the body of the request. The `Content-Type` HTTP header 298 | /// field of an encoded request is set to `application/x-plist`. 299 | public struct PropertyListEncoding: ParameterEncoding { 300 | 301 | // MARK: Properties 302 | 303 | /// Returns a default `PropertyListEncoding` instance. 304 | public static var `default`: PropertyListEncoding { return PropertyListEncoding() } 305 | 306 | /// Returns a `PropertyListEncoding` instance with xml formatting and default writing options. 307 | public static var xml: PropertyListEncoding { return PropertyListEncoding(format: .xml) } 308 | 309 | /// Returns a `PropertyListEncoding` instance with binary formatting and default writing options. 310 | public static var binary: PropertyListEncoding { return PropertyListEncoding(format: .binary) } 311 | 312 | /// The property list serialization format. 313 | public let format: PropertyListSerialization.PropertyListFormat 314 | 315 | /// The options for writing the parameters as plist data. 316 | public let options: PropertyListSerialization.WriteOptions 317 | 318 | // MARK: Initialization 319 | 320 | /// Creates a `PropertyListEncoding` instance using the specified format and options. 321 | /// 322 | /// - parameter format: The property list serialization format. 323 | /// - parameter options: The options for writing the parameters as plist data. 324 | /// 325 | /// - returns: The new `PropertyListEncoding` instance. 326 | public init( 327 | format: PropertyListSerialization.PropertyListFormat = .xml, 328 | options: PropertyListSerialization.WriteOptions = 0) 329 | { 330 | self.format = format 331 | self.options = options 332 | } 333 | 334 | // MARK: Encoding 335 | 336 | /// Creates a URL request by encoding parameters and applying them onto an existing request. 337 | /// 338 | /// - parameter urlRequest: The request to have parameters applied. 339 | /// - parameter parameters: The parameters to apply. 340 | /// 341 | /// - throws: An `Error` if the encoding process encounters an error. 342 | /// 343 | /// - returns: The encoded request. 344 | public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { 345 | var urlRequest = try urlRequest.asURLRequest() 346 | 347 | guard let parameters = parameters else { return urlRequest } 348 | 349 | do { 350 | let data = try PropertyListSerialization.data( 351 | fromPropertyList: parameters, 352 | format: format, 353 | options: options 354 | ) 355 | 356 | if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { 357 | urlRequest.setValue("application/x-plist", forHTTPHeaderField: "Content-Type") 358 | } 359 | 360 | urlRequest.httpBody = data 361 | } catch { 362 | throw AFError.parameterEncodingFailed(reason: .propertyListEncodingFailed(error: error)) 363 | } 364 | 365 | return urlRequest 366 | } 367 | } 368 | 369 | // MARK: - 370 | 371 | extension NSNumber { 372 | fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) } 373 | } 374 | --------------------------------------------------------------------------------