├── .gitignore ├── .swift-version ├── LICENSE ├── POP └── Negotiate │ ├── Negotiate.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── Negotiate.xcworkspace │ └── contents.xcworkspacedata │ ├── Negotiate │ ├── Api.swift │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── RequestCenter.swift │ ├── ViewController.swift │ └── YYGRequest.swift │ ├── NegotiateTests │ ├── Info.plist │ └── NegotiateTests.swift │ ├── NegotiateUITests │ ├── Info.plist │ └── NegotiateUITests.swift │ ├── Podfile │ ├── Podfile.lock │ └── Pods │ ├── Alamofire │ ├── LICENSE │ ├── README.md │ └── Source │ │ ├── AFError.swift │ │ ├── Alamofire.swift │ │ ├── DispatchQueue+Alamofire.swift │ │ ├── MultipartFormData.swift │ │ ├── NetworkReachabilityManager.swift │ │ ├── Notifications.swift │ │ ├── ParameterEncoding.swift │ │ ├── Request.swift │ │ ├── Response.swift │ │ ├── ResponseSerialization.swift │ │ ├── Result.swift │ │ ├── ServerTrustPolicy.swift │ │ ├── SessionDelegate.swift │ │ ├── SessionManager.swift │ │ ├── TaskDelegate.swift │ │ ├── Timeline.swift │ │ └── Validation.swift │ ├── Manifest.lock │ ├── Pods.xcodeproj │ └── project.pbxproj │ ├── SwiftyJSON │ ├── LICENSE │ ├── README.md │ └── Source │ │ └── SwiftyJSON.swift │ └── Target Support Files │ ├── Alamofire │ ├── Alamofire-dummy.m │ ├── Alamofire-prefix.pch │ ├── Alamofire-umbrella.h │ ├── Alamofire.modulemap │ ├── Alamofire.xcconfig │ └── Info.plist │ ├── Pods-Negotiate │ ├── Info.plist │ ├── Pods-Negotiate-acknowledgements.markdown │ ├── Pods-Negotiate-acknowledgements.plist │ ├── Pods-Negotiate-dummy.m │ ├── Pods-Negotiate-frameworks.sh │ ├── Pods-Negotiate-resources.sh │ ├── Pods-Negotiate-umbrella.h │ ├── Pods-Negotiate.debug.xcconfig │ ├── Pods-Negotiate.modulemap │ └── Pods-Negotiate.release.xcconfig │ └── SwiftyJSON │ ├── Info.plist │ ├── SwiftyJSON-dummy.m │ ├── SwiftyJSON-prefix.pch │ ├── SwiftyJSON-umbrella.h │ ├── SwiftyJSON.modulemap │ └── SwiftyJSON.xcconfig ├── README.md ├── YYGRegular.podspec ├── YYGRegular.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata └── YYGRegular ├── Info.plist ├── SwitchSegue.swift ├── UIView.swift ├── YYGRegular.h ├── YYGRegular.swift ├── YYGText.swift ├── YYGcategory.swift └── arrayDataSource.swift /.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 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 2.3 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 尹玉 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /POP/Negotiate/Negotiate.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /POP/Negotiate/Negotiate.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /POP/Negotiate/Negotiate/Api.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Api.swift 3 | // Negotiate 4 | // 5 | // Created by 区块国际-yin on 17/2/5. 6 | // Copyright © 2017年 区块国际-yin. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Api { 12 | static let host = "http://api.isanjie.com/" 13 | 14 | static func map(path: String) -> String { 15 | return host + path 16 | } 17 | 18 | static var goodsParticularsURL: String { 19 | return map(path: "goods/getgoods") 20 | } 21 | /// .... 接着继续其他接口的书写 22 | } 23 | 24 | -------------------------------------------------------------------------------- /POP/Negotiate/Negotiate/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Negotiate 4 | // 5 | // Created by 区块国际-yin on 17/2/5. 6 | // Copyright © 2017年 区块国际-yin. 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 | -------------------------------------------------------------------------------- /POP/Negotiate/Negotiate/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 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /POP/Negotiate/Negotiate/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 | -------------------------------------------------------------------------------- /POP/Negotiate/Negotiate/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 | -------------------------------------------------------------------------------- /POP/Negotiate/Negotiate/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 | NSAppTransportSecurity 38 | 39 | NSAllowsArbitraryLoads 40 | 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /POP/Negotiate/Negotiate/RequestCenter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RequestCenter.swift 3 | // Negotiate 4 | // 5 | // Created by 区块国际-yin on 17/2/5. 6 | // Copyright © 2017年 区块国际-yin. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Alamofire 11 | import SwiftyJSON 12 | 13 | 14 | /// 商品详情请求 15 | struct goodsParticulars: Request { 16 | 17 | var goodsId: String 18 | 19 | var path: String { 20 | return Api.goodsParticularsURL 21 | } 22 | 23 | var method: HTTPMethod = .post 24 | 25 | var parameter: [String : AnyObject] { 26 | return ["goods_id": goodsId as AnyObject] 27 | } 28 | 29 | typealias Analysis = ParticularsAnalysis 30 | } 31 | 32 | extension ParticularsAnalysis: Decodable { 33 | static func parse(anyData: Any) -> ParticularsAnalysis? { 34 | return ParticularsAnalysis(anyData: anyData) 35 | } 36 | } 37 | 38 | struct ParticularsAnalysis { 39 | 40 | var message: Bool 41 | var tempData: Any 42 | 43 | init?(anyData: Any) { 44 | 45 | let obj = JSON(anyData) 46 | 47 | guard let name = obj["errno"].int else { 48 | self.message = false 49 | return nil 50 | } 51 | 52 | if name == 2000 { 53 | self.message = true 54 | self.tempData = anyData 55 | } else { 56 | self.message = false 57 | self.tempData = anyData 58 | 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /POP/Negotiate/Negotiate/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Negotiate 4 | // 5 | // Created by 区块国际-yin on 17/2/5. 6 | // Copyright © 2017年 区块国际-yin. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | override func touchesBegan(_ touches: Set, with event: UIEvent?) { 24 | SessionRequestSender().send(goodsParticulars(goodsId: "580", method: .post), analysis: { ParticularsAnalysis in 25 | 26 | print(ParticularsAnalysis?.tempData as Any) 27 | // ParticularsAnalysis?.message 28 | // ParticularsAnalysis?.tempData 29 | 30 | }) 31 | } 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /POP/Negotiate/Negotiate/YYGRequest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YYGRequest.swift 3 | // Negotiate 4 | // 5 | // Created by 区块国际-yin on 17/2/5. 6 | // Copyright © 2017年 区块国际-yin. All rights reserved. 7 | // 8 | 9 | 10 | import Foundation 11 | import Alamofire 12 | 13 | protocol Request { 14 | 15 | var path: String { get } 16 | 17 | var method: HTTPMethod { get } 18 | 19 | var parameter: [String: AnyObject] { get } 20 | 21 | associatedtype Analysis: Decodable 22 | } 23 | 24 | protocol Decodable { 25 | static func parse(anyData: Any) -> Self? 26 | } 27 | 28 | protocol SenderRequest { 29 | func send(_ p: T, analysis: @escaping (T.Analysis?) -> Void) 30 | } 31 | 32 | struct SessionRequestSender: SenderRequest { 33 | func send(_ p: T, analysis: @escaping (T.Analysis?) -> Void) { 34 | 35 | Alamofire.request(p.path, method: p.method, parameters: p.parameter).responseJSON { (response) in 36 | switch response.result { 37 | case .success: 38 | if let anyData = response.result.value, let res = T.Analysis.parse(anyData: anyData) { 39 | DispatchQueue.main.async { 40 | analysis(res) 41 | } 42 | } 43 | case .failure(_): 44 | break 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /POP/Negotiate/NegotiateTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /POP/Negotiate/NegotiateTests/NegotiateTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NegotiateTests.swift 3 | // NegotiateTests 4 | // 5 | // Created by 区块国际-yin on 17/2/5. 6 | // Copyright © 2017年 区块国际-yin. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import Negotiate 11 | 12 | class NegotiateTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /POP/Negotiate/NegotiateUITests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /POP/Negotiate/NegotiateUITests/NegotiateUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NegotiateUITests.swift 3 | // NegotiateUITests 4 | // 5 | // Created by 区块国际-yin on 17/2/5. 6 | // Copyright © 2017年 区块国际-yin. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class NegotiateUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /POP/Negotiate/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, "8.0" 2 | use_frameworks! 3 | 4 | target :'Negotiate' do 5 | pod 'Alamofire' 6 | pod 'SwiftyJSON' 7 | end 8 | -------------------------------------------------------------------------------- /POP/Negotiate/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (4.3.0) 3 | - SwiftyJSON (3.1.4) 4 | 5 | DEPENDENCIES: 6 | - Alamofire 7 | - SwiftyJSON 8 | 9 | SPEC CHECKSUMS: 10 | Alamofire: 856a113053a7bc9cbe5d6367a555d773fc5cfef7 11 | SwiftyJSON: c2842d878f95482ffceec5709abc3d05680c0220 12 | 13 | PODFILE CHECKSUM: 8c772c32c8cf9841c37ee3edc4ea37bb18571dc4 14 | 15 | COCOAPODS: 1.1.0.beta.2 16 | -------------------------------------------------------------------------------- /POP/Negotiate/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 | -------------------------------------------------------------------------------- /POP/Negotiate/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 | -------------------------------------------------------------------------------- /POP/Negotiate/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 | public class NetworkReachabilityManager { 37 | /// Defines the various states of network reachability. 38 | /// 39 | /// - unknown: It is unknown whether the network is reachable. 40 | /// - notReachable: The network is not reachable. 41 | /// - reachable: The network is reachable. 42 | public enum NetworkReachabilityStatus { 43 | case unknown 44 | case notReachable 45 | case reachable(ConnectionType) 46 | } 47 | 48 | /// Defines the various connection types detected by reachability flags. 49 | /// 50 | /// - ethernetOrWiFi: The connection type is either over Ethernet or WiFi. 51 | /// - wwan: The connection type is a WWAN connection. 52 | public enum ConnectionType { 53 | case ethernetOrWiFi 54 | case wwan 55 | } 56 | 57 | /// A closure executed when the network reachability status changes. The closure takes a single argument: the 58 | /// network reachability status. 59 | public typealias Listener = (NetworkReachabilityStatus) -> Void 60 | 61 | // MARK: - Properties 62 | 63 | /// Whether the network is currently reachable. 64 | public var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi } 65 | 66 | /// Whether the network is currently reachable over the WWAN interface. 67 | public var isReachableOnWWAN: Bool { return networkReachabilityStatus == .reachable(.wwan) } 68 | 69 | /// Whether the network is currently reachable over Ethernet or WiFi interface. 70 | public var isReachableOnEthernetOrWiFi: Bool { return networkReachabilityStatus == .reachable(.ethernetOrWiFi) } 71 | 72 | /// The current network reachability status. 73 | public var networkReachabilityStatus: NetworkReachabilityStatus { 74 | guard let flags = self.flags else { return .unknown } 75 | return networkReachabilityStatusForFlags(flags) 76 | } 77 | 78 | /// The dispatch queue to execute the `listener` closure on. 79 | public var listenerQueue: DispatchQueue = DispatchQueue.main 80 | 81 | /// A closure executed when the network reachability status changes. 82 | public var listener: Listener? 83 | 84 | private var flags: SCNetworkReachabilityFlags? { 85 | var flags = SCNetworkReachabilityFlags() 86 | 87 | if SCNetworkReachabilityGetFlags(reachability, &flags) { 88 | return flags 89 | } 90 | 91 | return nil 92 | } 93 | 94 | private let reachability: SCNetworkReachability 95 | private var previousFlags: SCNetworkReachabilityFlags 96 | 97 | // MARK: - Initialization 98 | 99 | /// Creates a `NetworkReachabilityManager` instance with the specified host. 100 | /// 101 | /// - parameter host: The host used to evaluate network reachability. 102 | /// 103 | /// - returns: The new `NetworkReachabilityManager` instance. 104 | public convenience init?(host: String) { 105 | guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil } 106 | self.init(reachability: reachability) 107 | } 108 | 109 | /// Creates a `NetworkReachabilityManager` instance that monitors the address 0.0.0.0. 110 | /// 111 | /// Reachability treats the 0.0.0.0 address as a special token that causes it to monitor the general routing 112 | /// status of the device, both IPv4 and IPv6. 113 | /// 114 | /// - returns: The new `NetworkReachabilityManager` instance. 115 | public convenience init?() { 116 | var address = sockaddr_in() 117 | address.sin_len = UInt8(MemoryLayout.size) 118 | address.sin_family = sa_family_t(AF_INET) 119 | 120 | guard let reachability = withUnsafePointer(to: &address, { pointer in 121 | return pointer.withMemoryRebound(to: sockaddr.self, capacity: MemoryLayout.size) { 122 | return SCNetworkReachabilityCreateWithAddress(nil, $0) 123 | } 124 | }) else { return nil } 125 | 126 | self.init(reachability: reachability) 127 | } 128 | 129 | private init(reachability: SCNetworkReachability) { 130 | self.reachability = reachability 131 | self.previousFlags = SCNetworkReachabilityFlags() 132 | } 133 | 134 | deinit { 135 | stopListening() 136 | } 137 | 138 | // MARK: - Listening 139 | 140 | /// Starts listening for changes in network reachability status. 141 | /// 142 | /// - returns: `true` if listening was started successfully, `false` otherwise. 143 | @discardableResult 144 | public func startListening() -> Bool { 145 | var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil) 146 | context.info = Unmanaged.passUnretained(self).toOpaque() 147 | 148 | let callbackEnabled = SCNetworkReachabilitySetCallback( 149 | reachability, 150 | { (_, flags, info) in 151 | let reachability = Unmanaged.fromOpaque(info!).takeUnretainedValue() 152 | reachability.notifyListener(flags) 153 | }, 154 | &context 155 | ) 156 | 157 | let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue) 158 | 159 | listenerQueue.async { 160 | self.previousFlags = SCNetworkReachabilityFlags() 161 | self.notifyListener(self.flags ?? SCNetworkReachabilityFlags()) 162 | } 163 | 164 | return callbackEnabled && queueEnabled 165 | } 166 | 167 | /// Stops listening for changes in network reachability status. 168 | public func stopListening() { 169 | SCNetworkReachabilitySetCallback(reachability, nil, nil) 170 | SCNetworkReachabilitySetDispatchQueue(reachability, nil) 171 | } 172 | 173 | // MARK: - Internal - Listener Notification 174 | 175 | func notifyListener(_ flags: SCNetworkReachabilityFlags) { 176 | guard previousFlags != flags else { return } 177 | previousFlags = flags 178 | 179 | listener?(networkReachabilityStatusForFlags(flags)) 180 | } 181 | 182 | // MARK: - Internal - Network Reachability Status 183 | 184 | func networkReachabilityStatusForFlags(_ flags: SCNetworkReachabilityFlags) -> NetworkReachabilityStatus { 185 | guard flags.contains(.reachable) else { return .notReachable } 186 | 187 | var networkStatus: NetworkReachabilityStatus = .notReachable 188 | 189 | if !flags.contains(.connectionRequired) { networkStatus = .reachable(.ethernetOrWiFi) } 190 | 191 | if flags.contains(.connectionOnDemand) || flags.contains(.connectionOnTraffic) { 192 | if !flags.contains(.interventionRequired) { networkStatus = .reachable(.ethernetOrWiFi) } 193 | } 194 | 195 | #if os(iOS) 196 | if flags.contains(.isWWAN) { networkStatus = .reachable(.wwan) } 197 | #endif 198 | 199 | return networkStatus 200 | } 201 | } 202 | 203 | // MARK: - 204 | 205 | extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {} 206 | 207 | /// Returns whether the two network reachability status values are equal. 208 | /// 209 | /// - parameter lhs: The left-hand side value to compare. 210 | /// - parameter rhs: The right-hand side value to compare. 211 | /// 212 | /// - returns: `true` if the two values are equal, `false` otherwise. 213 | public func ==( 214 | lhs: NetworkReachabilityManager.NetworkReachabilityStatus, 215 | rhs: NetworkReachabilityManager.NetworkReachabilityStatus) 216 | -> Bool 217 | { 218 | switch (lhs, rhs) { 219 | case (.unknown, .unknown): 220 | return true 221 | case (.notReachable, .notReachable): 222 | return true 223 | case let (.reachable(lhsConnectionType), .reachable(rhsConnectionType)): 224 | return lhsConnectionType == rhsConnectionType 225 | default: 226 | return false 227 | } 228 | } 229 | 230 | #endif 231 | -------------------------------------------------------------------------------- /POP/Negotiate/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 | -------------------------------------------------------------------------------- /POP/Negotiate/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 | var escaped = "" 203 | 204 | //========================================================================================================== 205 | // 206 | // Batching is required for escaping due to an internal bug in iOS 8.1 and 8.2. Encoding more than a few 207 | // hundred Chinese characters causes various malloc error crashes. To avoid this issue until iOS 8 is no 208 | // longer supported, batching MUST be used for encoding. This introduces roughly a 20% overhead. For more 209 | // info, please refer to: 210 | // 211 | // - https://github.com/Alamofire/Alamofire/issues/206 212 | // 213 | //========================================================================================================== 214 | 215 | if #available(iOS 8.3, *) { 216 | escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string 217 | } else { 218 | let batchSize = 50 219 | var index = string.startIndex 220 | 221 | while index != string.endIndex { 222 | let startIndex = index 223 | let endIndex = string.index(index, offsetBy: batchSize, limitedBy: string.endIndex) ?? string.endIndex 224 | let range = startIndex.. String { 238 | var components: [(String, String)] = [] 239 | 240 | for key in parameters.keys.sorted(by: <) { 241 | let value = parameters[key]! 242 | components += queryComponents(fromKey: key, value: value) 243 | } 244 | 245 | return components.map { "\($0)=\($1)" }.joined(separator: "&") 246 | } 247 | 248 | private func encodesParametersInURL(with method: HTTPMethod) -> Bool { 249 | switch destination { 250 | case .queryString: 251 | return true 252 | case .httpBody: 253 | return false 254 | default: 255 | break 256 | } 257 | 258 | switch method { 259 | case .get, .head, .delete: 260 | return true 261 | default: 262 | return false 263 | } 264 | } 265 | } 266 | 267 | // MARK: - 268 | 269 | /// Uses `JSONSerialization` to create a JSON representation of the parameters object, which is set as the body of the 270 | /// request. The `Content-Type` HTTP header field of an encoded request is set to `application/json`. 271 | public struct JSONEncoding: ParameterEncoding { 272 | 273 | // MARK: Properties 274 | 275 | /// Returns a `JSONEncoding` instance with default writing options. 276 | public static var `default`: JSONEncoding { return JSONEncoding() } 277 | 278 | /// Returns a `JSONEncoding` instance with `.prettyPrinted` writing options. 279 | public static var prettyPrinted: JSONEncoding { return JSONEncoding(options: .prettyPrinted) } 280 | 281 | /// The options for writing the parameters as JSON data. 282 | public let options: JSONSerialization.WritingOptions 283 | 284 | // MARK: Initialization 285 | 286 | /// Creates a `JSONEncoding` instance using the specified options. 287 | /// 288 | /// - parameter options: The options for writing the parameters as JSON data. 289 | /// 290 | /// - returns: The new `JSONEncoding` instance. 291 | public init(options: JSONSerialization.WritingOptions = []) { 292 | self.options = options 293 | } 294 | 295 | // MARK: Encoding 296 | 297 | /// Creates a URL request by encoding parameters and applying them onto an existing request. 298 | /// 299 | /// - parameter urlRequest: The request to have parameters applied. 300 | /// - parameter parameters: The parameters to apply. 301 | /// 302 | /// - throws: An `Error` if the encoding process encounters an error. 303 | /// 304 | /// - returns: The encoded request. 305 | public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { 306 | var urlRequest = try urlRequest.asURLRequest() 307 | 308 | guard let parameters = parameters else { return urlRequest } 309 | 310 | do { 311 | let data = try JSONSerialization.data(withJSONObject: parameters, options: options) 312 | 313 | if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { 314 | urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") 315 | } 316 | 317 | urlRequest.httpBody = data 318 | } catch { 319 | throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error)) 320 | } 321 | 322 | return urlRequest 323 | } 324 | 325 | /// Creates a URL request by encoding the JSON object and setting the resulting data on the HTTP body. 326 | /// 327 | /// - parameter urlRequest: The request to apply the JSON object to. 328 | /// - parameter jsonObject: The JSON object to apply to the request. 329 | /// 330 | /// - throws: An `Error` if the encoding process encounters an error. 331 | /// 332 | /// - returns: The encoded request. 333 | public func encode(_ urlRequest: URLRequestConvertible, withJSONObject jsonObject: Any? = nil) throws -> URLRequest { 334 | var urlRequest = try urlRequest.asURLRequest() 335 | 336 | guard let jsonObject = jsonObject else { return urlRequest } 337 | 338 | do { 339 | let data = try JSONSerialization.data(withJSONObject: jsonObject, options: options) 340 | 341 | if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { 342 | urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") 343 | } 344 | 345 | urlRequest.httpBody = data 346 | } catch { 347 | throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error)) 348 | } 349 | 350 | return urlRequest 351 | } 352 | } 353 | 354 | // MARK: - 355 | 356 | /// Uses `PropertyListSerialization` to create a plist representation of the parameters object, according to the 357 | /// associated format and write options values, which is set as the body of the request. The `Content-Type` HTTP header 358 | /// field of an encoded request is set to `application/x-plist`. 359 | public struct PropertyListEncoding: ParameterEncoding { 360 | 361 | // MARK: Properties 362 | 363 | /// Returns a default `PropertyListEncoding` instance. 364 | public static var `default`: PropertyListEncoding { return PropertyListEncoding() } 365 | 366 | /// Returns a `PropertyListEncoding` instance with xml formatting and default writing options. 367 | public static var xml: PropertyListEncoding { return PropertyListEncoding(format: .xml) } 368 | 369 | /// Returns a `PropertyListEncoding` instance with binary formatting and default writing options. 370 | public static var binary: PropertyListEncoding { return PropertyListEncoding(format: .binary) } 371 | 372 | /// The property list serialization format. 373 | public let format: PropertyListSerialization.PropertyListFormat 374 | 375 | /// The options for writing the parameters as plist data. 376 | public let options: PropertyListSerialization.WriteOptions 377 | 378 | // MARK: Initialization 379 | 380 | /// Creates a `PropertyListEncoding` instance using the specified format and options. 381 | /// 382 | /// - parameter format: The property list serialization format. 383 | /// - parameter options: The options for writing the parameters as plist data. 384 | /// 385 | /// - returns: The new `PropertyListEncoding` instance. 386 | public init( 387 | format: PropertyListSerialization.PropertyListFormat = .xml, 388 | options: PropertyListSerialization.WriteOptions = 0) 389 | { 390 | self.format = format 391 | self.options = options 392 | } 393 | 394 | // MARK: Encoding 395 | 396 | /// Creates a URL request by encoding parameters and applying them onto an existing request. 397 | /// 398 | /// - parameter urlRequest: The request to have parameters applied. 399 | /// - parameter parameters: The parameters to apply. 400 | /// 401 | /// - throws: An `Error` if the encoding process encounters an error. 402 | /// 403 | /// - returns: The encoded request. 404 | public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { 405 | var urlRequest = try urlRequest.asURLRequest() 406 | 407 | guard let parameters = parameters else { return urlRequest } 408 | 409 | do { 410 | let data = try PropertyListSerialization.data( 411 | fromPropertyList: parameters, 412 | format: format, 413 | options: options 414 | ) 415 | 416 | if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil { 417 | urlRequest.setValue("application/x-plist", forHTTPHeaderField: "Content-Type") 418 | } 419 | 420 | urlRequest.httpBody = data 421 | } catch { 422 | throw AFError.parameterEncodingFailed(reason: .propertyListEncodingFailed(error: error)) 423 | } 424 | 425 | return urlRequest 426 | } 427 | } 428 | 429 | // MARK: - 430 | 431 | extension NSNumber { 432 | fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) } 433 | } 434 | -------------------------------------------------------------------------------- /POP/Negotiate/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 | /// The timeline of the complete lifecycle of the request. 42 | public let timeline: Timeline 43 | 44 | var _metrics: AnyObject? 45 | 46 | /// Creates a `DefaultDataResponse` instance from the specified parameters. 47 | /// 48 | /// - Parameters: 49 | /// - request: The URL request sent to the server. 50 | /// - response: The server's response to the URL request. 51 | /// - data: The data returned by the server. 52 | /// - error: The error encountered while executing or validating the request. 53 | /// - timeline: The timeline of the complete lifecycle of the request. `Timeline()` by default. 54 | /// - metrics: The task metrics containing the request / response statistics. `nil` by default. 55 | public init( 56 | request: URLRequest?, 57 | response: HTTPURLResponse?, 58 | data: Data?, 59 | error: Error?, 60 | timeline: Timeline = Timeline(), 61 | metrics: AnyObject? = nil) 62 | { 63 | self.request = request 64 | self.response = response 65 | self.data = data 66 | self.error = error 67 | self.timeline = timeline 68 | } 69 | } 70 | 71 | // MARK: - 72 | 73 | /// Used to store all data associated with a serialized response of a data or upload request. 74 | public struct DataResponse { 75 | /// The URL request sent to the server. 76 | public let request: URLRequest? 77 | 78 | /// The server's response to the URL request. 79 | public let response: HTTPURLResponse? 80 | 81 | /// The data returned by the server. 82 | public let data: Data? 83 | 84 | /// The result of response serialization. 85 | public let result: Result 86 | 87 | /// The timeline of the complete lifecycle of the request. 88 | public let timeline: Timeline 89 | 90 | /// Returns the associated value of the result if it is a success, `nil` otherwise. 91 | public var value: Value? { return result.value } 92 | 93 | /// Returns the associated error value if the result if it is a failure, `nil` otherwise. 94 | public var error: Error? { return result.error } 95 | 96 | var _metrics: AnyObject? 97 | 98 | /// Creates a `DataResponse` instance with the specified parameters derived from response serialization. 99 | /// 100 | /// - parameter request: The URL request sent to the server. 101 | /// - parameter response: The server's response to the URL request. 102 | /// - parameter data: The data returned by the server. 103 | /// - parameter result: The result of response serialization. 104 | /// - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`. 105 | /// 106 | /// - returns: The new `DataResponse` instance. 107 | public init( 108 | request: URLRequest?, 109 | response: HTTPURLResponse?, 110 | data: Data?, 111 | result: Result, 112 | timeline: Timeline = Timeline()) 113 | { 114 | self.request = request 115 | self.response = response 116 | self.data = data 117 | self.result = result 118 | self.timeline = timeline 119 | } 120 | } 121 | 122 | // MARK: - 123 | 124 | extension DataResponse: CustomStringConvertible, CustomDebugStringConvertible { 125 | /// The textual representation used when written to an output stream, which includes whether the result was a 126 | /// success or failure. 127 | public var description: String { 128 | return result.debugDescription 129 | } 130 | 131 | /// The debug textual representation used when written to an output stream, which includes the URL request, the URL 132 | /// response, the server data, the response serialization result and the timeline. 133 | public var debugDescription: String { 134 | var output: [String] = [] 135 | 136 | output.append(request != nil ? "[Request]: \(request!.httpMethod ?? "GET") \(request!)" : "[Request]: nil") 137 | output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil") 138 | output.append("[Data]: \(data?.count ?? 0) bytes") 139 | output.append("[Result]: \(result.debugDescription)") 140 | output.append("[Timeline]: \(timeline.debugDescription)") 141 | 142 | return output.joined(separator: "\n") 143 | } 144 | } 145 | 146 | // MARK: - 147 | 148 | /// Used to store all data associated with an non-serialized response of a download request. 149 | public struct DefaultDownloadResponse { 150 | /// The URL request sent to the server. 151 | public let request: URLRequest? 152 | 153 | /// The server's response to the URL request. 154 | public let response: HTTPURLResponse? 155 | 156 | /// The temporary destination URL of the data returned from the server. 157 | public let temporaryURL: URL? 158 | 159 | /// The final destination URL of the data returned from the server if it was moved. 160 | public let destinationURL: URL? 161 | 162 | /// The resume data generated if the request was cancelled. 163 | public let resumeData: Data? 164 | 165 | /// The error encountered while executing or validating the request. 166 | public let error: Error? 167 | 168 | /// The timeline of the complete lifecycle of the request. 169 | public let timeline: Timeline 170 | 171 | var _metrics: AnyObject? 172 | 173 | /// Creates a `DefaultDownloadResponse` instance from the specified parameters. 174 | /// 175 | /// - Parameters: 176 | /// - request: The URL request sent to the server. 177 | /// - response: The server's response to the URL request. 178 | /// - temporaryURL: The temporary destination URL of the data returned from the server. 179 | /// - destinationURL: The final destination URL of the data returned from the server if it was moved. 180 | /// - resumeData: The resume data generated if the request was cancelled. 181 | /// - error: The error encountered while executing or validating the request. 182 | /// - timeline: The timeline of the complete lifecycle of the request. `Timeline()` by default. 183 | /// - metrics: The task metrics containing the request / response statistics. `nil` by default. 184 | public init( 185 | request: URLRequest?, 186 | response: HTTPURLResponse?, 187 | temporaryURL: URL?, 188 | destinationURL: URL?, 189 | resumeData: Data?, 190 | error: Error?, 191 | timeline: Timeline = Timeline(), 192 | metrics: AnyObject? = nil) 193 | { 194 | self.request = request 195 | self.response = response 196 | self.temporaryURL = temporaryURL 197 | self.destinationURL = destinationURL 198 | self.resumeData = resumeData 199 | self.error = error 200 | self.timeline = timeline 201 | } 202 | } 203 | 204 | // MARK: - 205 | 206 | /// Used to store all data associated with a serialized response of a download request. 207 | public struct DownloadResponse { 208 | /// The URL request sent to the server. 209 | public let request: URLRequest? 210 | 211 | /// The server's response to the URL request. 212 | public let response: HTTPURLResponse? 213 | 214 | /// The temporary destination URL of the data returned from the server. 215 | public let temporaryURL: URL? 216 | 217 | /// The final destination URL of the data returned from the server if it was moved. 218 | public let destinationURL: URL? 219 | 220 | /// The resume data generated if the request was cancelled. 221 | public let resumeData: Data? 222 | 223 | /// The result of response serialization. 224 | public let result: Result 225 | 226 | /// The timeline of the complete lifecycle of the request. 227 | public let timeline: Timeline 228 | 229 | /// Returns the associated value of the result if it is a success, `nil` otherwise. 230 | public var value: Value? { return result.value } 231 | 232 | /// Returns the associated error value if the result if it is a failure, `nil` otherwise. 233 | public var error: Error? { return result.error } 234 | 235 | var _metrics: AnyObject? 236 | 237 | /// Creates a `DownloadResponse` instance with the specified parameters derived from response serialization. 238 | /// 239 | /// - parameter request: The URL request sent to the server. 240 | /// - parameter response: The server's response to the URL request. 241 | /// - parameter temporaryURL: The temporary destination URL of the data returned from the server. 242 | /// - parameter destinationURL: The final destination URL of the data returned from the server if it was moved. 243 | /// - parameter resumeData: The resume data generated if the request was cancelled. 244 | /// - parameter result: The result of response serialization. 245 | /// - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`. 246 | /// 247 | /// - returns: The new `DownloadResponse` instance. 248 | public init( 249 | request: URLRequest?, 250 | response: HTTPURLResponse?, 251 | temporaryURL: URL?, 252 | destinationURL: URL?, 253 | resumeData: Data?, 254 | result: Result, 255 | timeline: Timeline = Timeline()) 256 | { 257 | self.request = request 258 | self.response = response 259 | self.temporaryURL = temporaryURL 260 | self.destinationURL = destinationURL 261 | self.resumeData = resumeData 262 | self.result = result 263 | self.timeline = timeline 264 | } 265 | } 266 | 267 | // MARK: - 268 | 269 | extension DownloadResponse: CustomStringConvertible, CustomDebugStringConvertible { 270 | /// The textual representation used when written to an output stream, which includes whether the result was a 271 | /// success or failure. 272 | public var description: String { 273 | return result.debugDescription 274 | } 275 | 276 | /// The debug textual representation used when written to an output stream, which includes the URL request, the URL 277 | /// response, the temporary and destination URLs, the resume data, the response serialization result and the 278 | /// timeline. 279 | public var debugDescription: String { 280 | var output: [String] = [] 281 | 282 | output.append(request != nil ? "[Request]: \(request!.httpMethod ?? "GET") \(request!)" : "[Request]: nil") 283 | output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil") 284 | output.append("[TemporaryURL]: \(temporaryURL?.path ?? "nil")") 285 | output.append("[DestinationURL]: \(destinationURL?.path ?? "nil")") 286 | output.append("[ResumeData]: \(resumeData?.count ?? 0) bytes") 287 | output.append("[Result]: \(result.debugDescription)") 288 | output.append("[Timeline]: \(timeline.debugDescription)") 289 | 290 | return output.joined(separator: "\n") 291 | } 292 | } 293 | 294 | // MARK: - 295 | 296 | protocol Response { 297 | /// The task metrics containing the request / response statistics. 298 | var _metrics: AnyObject? { get set } 299 | mutating func add(_ metrics: AnyObject?) 300 | } 301 | 302 | extension Response { 303 | mutating func add(_ metrics: AnyObject?) { 304 | #if !os(watchOS) 305 | guard #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) else { return } 306 | guard let metrics = metrics as? URLSessionTaskMetrics else { return } 307 | 308 | _metrics = metrics 309 | #endif 310 | } 311 | } 312 | 313 | // MARK: - 314 | 315 | @available(iOS 10.0, macOS 10.12, tvOS 10.0, *) 316 | extension DefaultDataResponse: Response { 317 | #if !os(watchOS) 318 | /// The task metrics containing the request / response statistics. 319 | public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } 320 | #endif 321 | } 322 | 323 | @available(iOS 10.0, macOS 10.12, tvOS 10.0, *) 324 | extension DataResponse: Response { 325 | #if !os(watchOS) 326 | /// The task metrics containing the request / response statistics. 327 | public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } 328 | #endif 329 | } 330 | 331 | @available(iOS 10.0, macOS 10.12, tvOS 10.0, *) 332 | extension DefaultDownloadResponse: Response { 333 | #if !os(watchOS) 334 | /// The task metrics containing the request / response statistics. 335 | public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } 336 | #endif 337 | } 338 | 339 | @available(iOS 10.0, macOS 10.12, tvOS 10.0, *) 340 | extension DownloadResponse: Response { 341 | #if !os(watchOS) 342 | /// The task metrics containing the request / response statistics. 343 | public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics } 344 | #endif 345 | } 346 | -------------------------------------------------------------------------------- /POP/Negotiate/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 | -------------------------------------------------------------------------------- /POP/Negotiate/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 | /// - performRevokedEvaluation: Uses the default and revoked server trust evaluations allowing you to control whether to 92 | /// validate the host provided by the challenge as well as specify the revocation flags for 93 | /// testing for revoked certificates. Apple platforms did not start testing for revoked 94 | /// certificates automatically until iOS 10.1, macOS 10.12 and tvOS 10.1 which is 95 | /// demonstrated in our TLS tests. Applications are encouraged to always validate the host 96 | /// in production environments to guarantee the validity of the server's certificate chain. 97 | /// 98 | /// - pinCertificates: Uses the pinned certificates to validate the server trust. The server trust is 99 | /// considered valid if one of the pinned certificates match one of the server certificates. 100 | /// By validating both the certificate chain and host, certificate 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 | /// - pinPublicKeys: Uses the pinned public keys to validate the server trust. The server trust is considered 106 | /// valid if one of the pinned public keys match one of the server certificate public keys. 107 | /// By validating both the certificate chain and host, public key pinning provides a very 108 | /// secure form of server trust validation mitigating most, if not all, MITM attacks. 109 | /// Applications are encouraged to always validate the host and require a valid certificate 110 | /// chain in production environments. 111 | /// 112 | /// - disableEvaluation: Disables all evaluation which in turn will always consider any server trust as valid. 113 | /// 114 | /// - customEvaluation: Uses the associated closure to evaluate the validity of the server trust. 115 | public enum ServerTrustPolicy { 116 | case performDefaultEvaluation(validateHost: Bool) 117 | case performRevokedEvaluation(validateHost: Bool, revocationFlags: CFOptionFlags) 118 | case pinCertificates(certificates: [SecCertificate], validateCertificateChain: Bool, validateHost: Bool) 119 | case pinPublicKeys(publicKeys: [SecKey], validateCertificateChain: Bool, validateHost: Bool) 120 | case disableEvaluation 121 | case customEvaluation((_ serverTrust: SecTrust, _ host: String) -> Bool) 122 | 123 | // MARK: - Bundle Location 124 | 125 | /// Returns all certificates within the given bundle with a `.cer` file extension. 126 | /// 127 | /// - parameter bundle: The bundle to search for all `.cer` files. 128 | /// 129 | /// - returns: All certificates within the given bundle. 130 | public static func certificates(in bundle: Bundle = Bundle.main) -> [SecCertificate] { 131 | var certificates: [SecCertificate] = [] 132 | 133 | let paths = Set([".cer", ".CER", ".crt", ".CRT", ".der", ".DER"].map { fileExtension in 134 | bundle.paths(forResourcesOfType: fileExtension, inDirectory: nil) 135 | }.joined()) 136 | 137 | for path in paths { 138 | if 139 | let certificateData = try? Data(contentsOf: URL(fileURLWithPath: path)) as CFData, 140 | let certificate = SecCertificateCreateWithData(nil, certificateData) 141 | { 142 | certificates.append(certificate) 143 | } 144 | } 145 | 146 | return certificates 147 | } 148 | 149 | /// Returns all public keys within the given bundle with a `.cer` file extension. 150 | /// 151 | /// - parameter bundle: The bundle to search for all `*.cer` files. 152 | /// 153 | /// - returns: All public keys within the given bundle. 154 | public static func publicKeys(in bundle: Bundle = Bundle.main) -> [SecKey] { 155 | var publicKeys: [SecKey] = [] 156 | 157 | for certificate in certificates(in: bundle) { 158 | if let publicKey = publicKey(for: certificate) { 159 | publicKeys.append(publicKey) 160 | } 161 | } 162 | 163 | return publicKeys 164 | } 165 | 166 | // MARK: - Evaluation 167 | 168 | /// Evaluates whether the server trust is valid for the given host. 169 | /// 170 | /// - parameter serverTrust: The server trust to evaluate. 171 | /// - parameter host: The host of the challenge protection space. 172 | /// 173 | /// - returns: Whether the server trust is valid. 174 | public func evaluate(_ serverTrust: SecTrust, forHost host: String) -> Bool { 175 | var serverTrustIsValid = false 176 | 177 | switch self { 178 | case let .performDefaultEvaluation(validateHost): 179 | let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) 180 | SecTrustSetPolicies(serverTrust, policy) 181 | 182 | serverTrustIsValid = trustIsValid(serverTrust) 183 | case let .performRevokedEvaluation(validateHost, revocationFlags): 184 | let defaultPolicy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) 185 | let revokedPolicy = SecPolicyCreateRevocation(revocationFlags) 186 | SecTrustSetPolicies(serverTrust, [defaultPolicy, revokedPolicy] as CFTypeRef) 187 | 188 | serverTrustIsValid = trustIsValid(serverTrust) 189 | case let .pinCertificates(pinnedCertificates, validateCertificateChain, validateHost): 190 | if validateCertificateChain { 191 | let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) 192 | SecTrustSetPolicies(serverTrust, policy) 193 | 194 | SecTrustSetAnchorCertificates(serverTrust, pinnedCertificates as CFArray) 195 | SecTrustSetAnchorCertificatesOnly(serverTrust, true) 196 | 197 | serverTrustIsValid = trustIsValid(serverTrust) 198 | } else { 199 | let serverCertificatesDataArray = certificateData(for: serverTrust) 200 | let pinnedCertificatesDataArray = certificateData(for: pinnedCertificates) 201 | 202 | outerLoop: for serverCertificateData in serverCertificatesDataArray { 203 | for pinnedCertificateData in pinnedCertificatesDataArray { 204 | if serverCertificateData == pinnedCertificateData { 205 | serverTrustIsValid = true 206 | break outerLoop 207 | } 208 | } 209 | } 210 | } 211 | case let .pinPublicKeys(pinnedPublicKeys, validateCertificateChain, validateHost): 212 | var certificateChainEvaluationPassed = true 213 | 214 | if validateCertificateChain { 215 | let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil) 216 | SecTrustSetPolicies(serverTrust, policy) 217 | 218 | certificateChainEvaluationPassed = trustIsValid(serverTrust) 219 | } 220 | 221 | if certificateChainEvaluationPassed { 222 | outerLoop: for serverPublicKey in ServerTrustPolicy.publicKeys(for: serverTrust) as [AnyObject] { 223 | for pinnedPublicKey in pinnedPublicKeys as [AnyObject] { 224 | if serverPublicKey.isEqual(pinnedPublicKey) { 225 | serverTrustIsValid = true 226 | break outerLoop 227 | } 228 | } 229 | } 230 | } 231 | case .disableEvaluation: 232 | serverTrustIsValid = true 233 | case let .customEvaluation(closure): 234 | serverTrustIsValid = closure(serverTrust, host) 235 | } 236 | 237 | return serverTrustIsValid 238 | } 239 | 240 | // MARK: - Private - Trust Validation 241 | 242 | private func trustIsValid(_ trust: SecTrust) -> Bool { 243 | var isValid = false 244 | 245 | var result = SecTrustResultType.invalid 246 | let status = SecTrustEvaluate(trust, &result) 247 | 248 | if status == errSecSuccess { 249 | let unspecified = SecTrustResultType.unspecified 250 | let proceed = SecTrustResultType.proceed 251 | 252 | 253 | isValid = result == unspecified || result == proceed 254 | } 255 | 256 | return isValid 257 | } 258 | 259 | // MARK: - Private - Certificate Data 260 | 261 | private func certificateData(for trust: SecTrust) -> [Data] { 262 | var certificates: [SecCertificate] = [] 263 | 264 | for index in 0.. [Data] { 274 | return certificates.map { SecCertificateCopyData($0) as Data } 275 | } 276 | 277 | // MARK: - Private - Public Key Extraction 278 | 279 | private static func publicKeys(for trust: SecTrust) -> [SecKey] { 280 | var publicKeys: [SecKey] = [] 281 | 282 | for index in 0.. SecKey? { 295 | var publicKey: SecKey? 296 | 297 | let policy = SecPolicyCreateBasicX509() 298 | var trust: SecTrust? 299 | let trustCreationStatus = SecTrustCreateWithCertificates(certificate, policy, &trust) 300 | 301 | if let trust = trust, trustCreationStatus == errSecSuccess { 302 | publicKey = SecTrustCopyPublicKey(trust) 303 | } 304 | 305 | return publicKey 306 | } 307 | } 308 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Alamofire/Source/TaskDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TaskDelegate.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 | /// The task delegate is responsible for handling all delegate callbacks for the underlying task as well as 28 | /// executing all operations attached to the serial operation queue upon task completion. 29 | open class TaskDelegate: NSObject { 30 | 31 | // MARK: Properties 32 | 33 | /// The serial operation queue used to execute all operations after the task completes. 34 | open let queue: OperationQueue 35 | 36 | /// The data returned by the server. 37 | public var data: Data? { return nil } 38 | 39 | /// The error generated throughout the lifecyle of the task. 40 | public var error: Error? 41 | 42 | var task: URLSessionTask? { 43 | didSet { reset() } 44 | } 45 | 46 | var initialResponseTime: CFAbsoluteTime? 47 | var credential: URLCredential? 48 | var metrics: AnyObject? // URLSessionTaskMetrics 49 | 50 | // MARK: Lifecycle 51 | 52 | init(task: URLSessionTask?) { 53 | self.task = task 54 | 55 | self.queue = { 56 | let operationQueue = OperationQueue() 57 | 58 | operationQueue.maxConcurrentOperationCount = 1 59 | operationQueue.isSuspended = true 60 | operationQueue.qualityOfService = .utility 61 | 62 | return operationQueue 63 | }() 64 | } 65 | 66 | func reset() { 67 | error = nil 68 | initialResponseTime = nil 69 | } 70 | 71 | // MARK: URLSessionTaskDelegate 72 | 73 | var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> URLRequest?)? 74 | var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))? 75 | var taskNeedNewBodyStream: ((URLSession, URLSessionTask) -> InputStream?)? 76 | var taskDidCompleteWithError: ((URLSession, URLSessionTask, Error?) -> Void)? 77 | 78 | @objc(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:) 79 | func urlSession( 80 | _ session: URLSession, 81 | task: URLSessionTask, 82 | willPerformHTTPRedirection response: HTTPURLResponse, 83 | newRequest request: URLRequest, 84 | completionHandler: @escaping (URLRequest?) -> Void) 85 | { 86 | var redirectRequest: URLRequest? = request 87 | 88 | if let taskWillPerformHTTPRedirection = taskWillPerformHTTPRedirection { 89 | redirectRequest = taskWillPerformHTTPRedirection(session, task, response, request) 90 | } 91 | 92 | completionHandler(redirectRequest) 93 | } 94 | 95 | @objc(URLSession:task:didReceiveChallenge:completionHandler:) 96 | func urlSession( 97 | _ session: URLSession, 98 | task: URLSessionTask, 99 | didReceive challenge: URLAuthenticationChallenge, 100 | completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) 101 | { 102 | var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling 103 | var credential: URLCredential? 104 | 105 | if let taskDidReceiveChallenge = taskDidReceiveChallenge { 106 | (disposition, credential) = taskDidReceiveChallenge(session, task, challenge) 107 | } else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { 108 | let host = challenge.protectionSpace.host 109 | 110 | if 111 | let serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicy(forHost: host), 112 | let serverTrust = challenge.protectionSpace.serverTrust 113 | { 114 | if serverTrustPolicy.evaluate(serverTrust, forHost: host) { 115 | disposition = .useCredential 116 | credential = URLCredential(trust: serverTrust) 117 | } else { 118 | disposition = .cancelAuthenticationChallenge 119 | } 120 | } 121 | } else { 122 | if challenge.previousFailureCount > 0 { 123 | disposition = .rejectProtectionSpace 124 | } else { 125 | credential = self.credential ?? session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace) 126 | 127 | if credential != nil { 128 | disposition = .useCredential 129 | } 130 | } 131 | } 132 | 133 | completionHandler(disposition, credential) 134 | } 135 | 136 | @objc(URLSession:task:needNewBodyStream:) 137 | func urlSession( 138 | _ session: URLSession, 139 | task: URLSessionTask, 140 | needNewBodyStream completionHandler: @escaping (InputStream?) -> Void) 141 | { 142 | var bodyStream: InputStream? 143 | 144 | if let taskNeedNewBodyStream = taskNeedNewBodyStream { 145 | bodyStream = taskNeedNewBodyStream(session, task) 146 | } 147 | 148 | completionHandler(bodyStream) 149 | } 150 | 151 | @objc(URLSession:task:didCompleteWithError:) 152 | func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { 153 | if let taskDidCompleteWithError = taskDidCompleteWithError { 154 | taskDidCompleteWithError(session, task, error) 155 | } else { 156 | if let error = error { 157 | if self.error == nil { self.error = error } 158 | 159 | if 160 | let downloadDelegate = self as? DownloadTaskDelegate, 161 | let resumeData = (error as NSError).userInfo[NSURLSessionDownloadTaskResumeData] as? Data 162 | { 163 | downloadDelegate.resumeData = resumeData 164 | } 165 | } 166 | 167 | queue.isSuspended = false 168 | } 169 | } 170 | } 171 | 172 | // MARK: - 173 | 174 | class DataTaskDelegate: TaskDelegate, URLSessionDataDelegate { 175 | 176 | // MARK: Properties 177 | 178 | var dataTask: URLSessionDataTask { return task as! URLSessionDataTask } 179 | 180 | override var data: Data? { 181 | if dataStream != nil { 182 | return nil 183 | } else { 184 | return mutableData 185 | } 186 | } 187 | 188 | var progress: Progress 189 | var progressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)? 190 | 191 | var dataStream: ((_ data: Data) -> Void)? 192 | 193 | private var totalBytesReceived: Int64 = 0 194 | private var mutableData: Data 195 | 196 | private var expectedContentLength: Int64? 197 | 198 | // MARK: Lifecycle 199 | 200 | override init(task: URLSessionTask?) { 201 | mutableData = Data() 202 | progress = Progress(totalUnitCount: 0) 203 | 204 | super.init(task: task) 205 | } 206 | 207 | override func reset() { 208 | super.reset() 209 | 210 | progress = Progress(totalUnitCount: 0) 211 | totalBytesReceived = 0 212 | mutableData = Data() 213 | expectedContentLength = nil 214 | } 215 | 216 | // MARK: URLSessionDataDelegate 217 | 218 | var dataTaskDidReceiveResponse: ((URLSession, URLSessionDataTask, URLResponse) -> URLSession.ResponseDisposition)? 219 | var dataTaskDidBecomeDownloadTask: ((URLSession, URLSessionDataTask, URLSessionDownloadTask) -> Void)? 220 | var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)? 221 | var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)? 222 | 223 | func urlSession( 224 | _ session: URLSession, 225 | dataTask: URLSessionDataTask, 226 | didReceive response: URLResponse, 227 | completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) 228 | { 229 | var disposition: URLSession.ResponseDisposition = .allow 230 | 231 | expectedContentLength = response.expectedContentLength 232 | 233 | if let dataTaskDidReceiveResponse = dataTaskDidReceiveResponse { 234 | disposition = dataTaskDidReceiveResponse(session, dataTask, response) 235 | } 236 | 237 | completionHandler(disposition) 238 | } 239 | 240 | func urlSession( 241 | _ session: URLSession, 242 | dataTask: URLSessionDataTask, 243 | didBecome downloadTask: URLSessionDownloadTask) 244 | { 245 | dataTaskDidBecomeDownloadTask?(session, dataTask, downloadTask) 246 | } 247 | 248 | func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { 249 | if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() } 250 | 251 | if let dataTaskDidReceiveData = dataTaskDidReceiveData { 252 | dataTaskDidReceiveData(session, dataTask, data) 253 | } else { 254 | if let dataStream = dataStream { 255 | dataStream(data) 256 | } else { 257 | mutableData.append(data) 258 | } 259 | 260 | let bytesReceived = Int64(data.count) 261 | totalBytesReceived += bytesReceived 262 | let totalBytesExpected = dataTask.response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown 263 | 264 | progress.totalUnitCount = totalBytesExpected 265 | progress.completedUnitCount = totalBytesReceived 266 | 267 | if let progressHandler = progressHandler { 268 | progressHandler.queue.async { progressHandler.closure(self.progress) } 269 | } 270 | } 271 | } 272 | 273 | func urlSession( 274 | _ session: URLSession, 275 | dataTask: URLSessionDataTask, 276 | willCacheResponse proposedResponse: CachedURLResponse, 277 | completionHandler: @escaping (CachedURLResponse?) -> Void) 278 | { 279 | var cachedResponse: CachedURLResponse? = proposedResponse 280 | 281 | if let dataTaskWillCacheResponse = dataTaskWillCacheResponse { 282 | cachedResponse = dataTaskWillCacheResponse(session, dataTask, proposedResponse) 283 | } 284 | 285 | completionHandler(cachedResponse) 286 | } 287 | } 288 | 289 | // MARK: - 290 | 291 | class DownloadTaskDelegate: TaskDelegate, URLSessionDownloadDelegate { 292 | 293 | // MARK: Properties 294 | 295 | var downloadTask: URLSessionDownloadTask { return task as! URLSessionDownloadTask } 296 | 297 | var progress: Progress 298 | var progressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)? 299 | 300 | var resumeData: Data? 301 | override var data: Data? { return resumeData } 302 | 303 | var destination: DownloadRequest.DownloadFileDestination? 304 | 305 | var temporaryURL: URL? 306 | var destinationURL: URL? 307 | 308 | var fileURL: URL? { return destination != nil ? destinationURL : temporaryURL } 309 | 310 | // MARK: Lifecycle 311 | 312 | override init(task: URLSessionTask?) { 313 | progress = Progress(totalUnitCount: 0) 314 | super.init(task: task) 315 | } 316 | 317 | override func reset() { 318 | super.reset() 319 | 320 | progress = Progress(totalUnitCount: 0) 321 | resumeData = nil 322 | } 323 | 324 | // MARK: URLSessionDownloadDelegate 325 | 326 | var downloadTaskDidFinishDownloadingToURL: ((URLSession, URLSessionDownloadTask, URL) -> URL)? 327 | var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)? 328 | var downloadTaskDidResumeAtOffset: ((URLSession, URLSessionDownloadTask, Int64, Int64) -> Void)? 329 | 330 | func urlSession( 331 | _ session: URLSession, 332 | downloadTask: URLSessionDownloadTask, 333 | didFinishDownloadingTo location: URL) 334 | { 335 | temporaryURL = location 336 | 337 | guard 338 | let destination = destination, 339 | let response = downloadTask.response as? HTTPURLResponse 340 | else { return } 341 | 342 | let result = destination(location, response) 343 | let destinationURL = result.destinationURL 344 | let options = result.options 345 | 346 | self.destinationURL = destinationURL 347 | 348 | do { 349 | if options.contains(.removePreviousFile), FileManager.default.fileExists(atPath: destinationURL.path) { 350 | try FileManager.default.removeItem(at: destinationURL) 351 | } 352 | 353 | if options.contains(.createIntermediateDirectories) { 354 | let directory = destinationURL.deletingLastPathComponent() 355 | try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) 356 | } 357 | 358 | try FileManager.default.moveItem(at: location, to: destinationURL) 359 | } catch { 360 | self.error = error 361 | } 362 | } 363 | 364 | func urlSession( 365 | _ session: URLSession, 366 | downloadTask: URLSessionDownloadTask, 367 | didWriteData bytesWritten: Int64, 368 | totalBytesWritten: Int64, 369 | totalBytesExpectedToWrite: Int64) 370 | { 371 | if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() } 372 | 373 | if let downloadTaskDidWriteData = downloadTaskDidWriteData { 374 | downloadTaskDidWriteData( 375 | session, 376 | downloadTask, 377 | bytesWritten, 378 | totalBytesWritten, 379 | totalBytesExpectedToWrite 380 | ) 381 | } else { 382 | progress.totalUnitCount = totalBytesExpectedToWrite 383 | progress.completedUnitCount = totalBytesWritten 384 | 385 | if let progressHandler = progressHandler { 386 | progressHandler.queue.async { progressHandler.closure(self.progress) } 387 | } 388 | } 389 | } 390 | 391 | func urlSession( 392 | _ session: URLSession, 393 | downloadTask: URLSessionDownloadTask, 394 | didResumeAtOffset fileOffset: Int64, 395 | expectedTotalBytes: Int64) 396 | { 397 | if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset { 398 | downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes) 399 | } else { 400 | progress.totalUnitCount = expectedTotalBytes 401 | progress.completedUnitCount = fileOffset 402 | } 403 | } 404 | } 405 | 406 | // MARK: - 407 | 408 | class UploadTaskDelegate: DataTaskDelegate { 409 | 410 | // MARK: Properties 411 | 412 | var uploadTask: URLSessionUploadTask { return task as! URLSessionUploadTask } 413 | 414 | var uploadProgress: Progress 415 | var uploadProgressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)? 416 | 417 | // MARK: Lifecycle 418 | 419 | override init(task: URLSessionTask?) { 420 | uploadProgress = Progress(totalUnitCount: 0) 421 | super.init(task: task) 422 | } 423 | 424 | override func reset() { 425 | super.reset() 426 | uploadProgress = Progress(totalUnitCount: 0) 427 | } 428 | 429 | // MARK: URLSessionTaskDelegate 430 | 431 | var taskDidSendBodyData: ((URLSession, URLSessionTask, Int64, Int64, Int64) -> Void)? 432 | 433 | func URLSession( 434 | _ session: URLSession, 435 | task: URLSessionTask, 436 | didSendBodyData bytesSent: Int64, 437 | totalBytesSent: Int64, 438 | totalBytesExpectedToSend: Int64) 439 | { 440 | if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() } 441 | 442 | if let taskDidSendBodyData = taskDidSendBodyData { 443 | taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend) 444 | } else { 445 | uploadProgress.totalUnitCount = totalBytesExpectedToSend 446 | uploadProgress.completedUnitCount = totalBytesSent 447 | 448 | if let uploadProgressHandler = uploadProgressHandler { 449 | uploadProgressHandler.queue.async { uploadProgressHandler.closure(self.uploadProgress) } 450 | } 451 | } 452 | } 453 | } 454 | -------------------------------------------------------------------------------- /POP/Negotiate/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 | -------------------------------------------------------------------------------- /POP/Negotiate/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 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Alamofire (4.3.0) 3 | - SwiftyJSON (3.1.4) 4 | 5 | DEPENDENCIES: 6 | - Alamofire 7 | - SwiftyJSON 8 | 9 | SPEC CHECKSUMS: 10 | Alamofire: 856a113053a7bc9cbe5d6367a555d773fc5cfef7 11 | SwiftyJSON: c2842d878f95482ffceec5709abc3d05680c0220 12 | 13 | PODFILE CHECKSUM: 8c772c32c8cf9841c37ee3edc4ea37bb18571dc4 14 | 15 | COCOAPODS: 1.1.0.beta.2 16 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/SwiftyJSON/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ruoyu Fu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/SwiftyJSON/README.md: -------------------------------------------------------------------------------- 1 | # SwiftyJSON 2 | 3 | [![Travis CI](https://travis-ci.org/SwiftyJSON/SwiftyJSON.svg?branch=master)](https://travis-ci.org/SwiftyJSON/SwiftyJSON) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) ![CocoaPods](https://img.shields.io/cocoapods/v/SwiftyJSON.svg) ![Platform](https://img.shields.io/badge/platforms-iOS%208.0+%20%7C%20macOS%2010.10+%20%7C%20tvOS%209.0+%20%7C%20watchOS%202.0+-333333.svg) 4 | 5 | SwiftyJSON makes it easy to deal with JSON data in Swift. 6 | 7 | 1. [Why is the typical JSON handling in Swift NOT good](#why-is-the-typical-json-handling-in-swift-not-good) 8 | 2. [Requirements](#requirements) 9 | 3. [Integration](#integration) 10 | 4. [Usage](#usage) 11 | - [Initialization](#initialization) 12 | - [Subscript](#subscript) 13 | - [Loop](#loop) 14 | - [Error](#error) 15 | - [Optional getter](#optional-getter) 16 | - [Non-optional getter](#non-optional-getter) 17 | - [Setter](#setter) 18 | - [Raw object](#raw-object) 19 | - [Literal convertibles](#literal-convertibles) 20 | - [Merging](#merging) 21 | 5. [Work with Alamofire](#work-with-alamofire) 22 | 23 | > For Legacy Swift support, take a look at the [swift2 branch](https://github.com/SwiftyJSON/SwiftyJSON/tree/swift2) 24 | 25 | > [中文介绍](http://tangplin.github.io/swiftyjson/) 26 | 27 | 28 | ## Why is the typical JSON handling in Swift NOT good? 29 | 30 | Swift is very strict about types. But although explicit typing is good for saving us from mistakes, it becomes painful when dealing with JSON and other areas that are, by nature, implicit about types. 31 | 32 | Take the Twitter API for example. Say we want to retrieve a user's "name" value of some tweet in Swift (according to Twitter's API https://dev.twitter.com/docs/api/1.1/get/statuses/home_timeline). 33 | 34 | The code would look like this: 35 | 36 | ```swift 37 | if let statusesArray = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]], 38 | let user = statusesArray[0]["user"] as? [String: Any], 39 | let username = user["name"] as? String { 40 | // Finally we got the username 41 | } 42 | ``` 43 | 44 | It's not good. 45 | 46 | Even if we use optional chaining, it would be messy: 47 | 48 | ```swift 49 | if let JSONObject = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]], 50 | let username = (JSONObject[0]["user"] as? [String: Any])?["name"] as? String { 51 | // There's our username 52 | } 53 | ``` 54 | 55 | An unreadable mess--for something that should really be simple! 56 | 57 | With SwiftyJSON all you have to do is: 58 | 59 | ```swift 60 | let json = JSON(data: dataFromNetworking) 61 | if let userName = json[0]["user"]["name"].string { 62 | //Now you got your value 63 | } 64 | ``` 65 | 66 | And don't worry about the Optional Wrapping thing. It's done for you automatically. 67 | 68 | ```swift 69 | let json = JSON(data: dataFromNetworking) 70 | if let userName = json[999999]["wrong_key"]["wrong_name"].string { 71 | //Calm down, take it easy, the ".string" property still produces the correct Optional String type with safety 72 | } else { 73 | //Print the error 74 | print(json[999999]["wrong_key"]["wrong_name"]) 75 | } 76 | ``` 77 | 78 | ## Requirements 79 | 80 | - iOS 8.0+ | macOS 10.10+ | tvOS 9.0+ | watchOS 2.0+ 81 | - Xcode 8 82 | 83 | ## Integration 84 | 85 | #### CocoaPods (iOS 8+, OS X 10.9+) 86 | 87 | You can use [CocoaPods](http://cocoapods.org/) to install `SwiftyJSON`by adding it to your `Podfile`: 88 | 89 | ```ruby 90 | platform :ios, '8.0' 91 | use_frameworks! 92 | 93 | target 'MyApp' do 94 | pod 'SwiftyJSON' 95 | end 96 | ``` 97 | 98 | Note that this requires CocoaPods version 36, and your iOS deployment target to be at least 8.0: 99 | 100 | 101 | #### Carthage (iOS 8+, OS X 10.9+) 102 | 103 | You can use [Carthage](https://github.com/Carthage/Carthage) to install `SwiftyJSON` by adding it to your `Cartfile`: 104 | 105 | ``` 106 | github "SwiftyJSON/SwiftyJSON" 107 | ``` 108 | 109 | #### Swift Package Manager 110 | 111 | You can use [The Swift Package Manager](https://swift.org/package-manager) to install `SwiftyJSON` by adding the proper description to your `Package.swift` file: 112 | 113 | ```swift 114 | import PackageDescription 115 | 116 | let package = Package( 117 | name: "YOUR_PROJECT_NAME", 118 | targets: [], 119 | dependencies: [ 120 | .Package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", versions: Version(1,0,0).. = json["list"].arrayValue 319 | ``` 320 | 321 | ```swift 322 | //If not a Dictionary or nil, return [:] 323 | let user: Dictionary = json["user"].dictionaryValue 324 | ``` 325 | 326 | #### Setter 327 | 328 | ```swift 329 | json["name"] = JSON("new-name") 330 | json[0] = JSON(1) 331 | ``` 332 | 333 | ```swift 334 | json["id"].int = 1234567890 335 | json["coordinate"].double = 8766.766 336 | json["name"].string = "Jack" 337 | json.arrayObject = [1,2,3,4] 338 | json.dictionaryObject = ["name":"Jack", "age":25] 339 | ``` 340 | 341 | #### Raw object 342 | 343 | ```swift 344 | let jsonObject: Any = json.object 345 | ``` 346 | 347 | ```swift 348 | if let jsonObject: Any = json.rawValue 349 | ``` 350 | 351 | ```swift 352 | //convert the JSON to raw NSData 353 | if let data = json.rawData() { 354 | //Do something you want 355 | } 356 | ``` 357 | 358 | ```swift 359 | //convert the JSON to a raw String 360 | if let string = json.rawString() { 361 | //Do something you want 362 | } 363 | ``` 364 | 365 | #### Existence 366 | 367 | ```swift 368 | //shows you whether value specified in JSON or not 369 | if json["name"].exists() 370 | ``` 371 | 372 | #### Literal convertibles 373 | 374 | For more info about literal convertibles: [Swift Literal Convertibles](http://nshipster.com/swift-literal-convertible/) 375 | 376 | ```swift 377 | //StringLiteralConvertible 378 | let json: JSON = "I'm a json" 379 | ``` 380 | 381 | ```swift 382 | //IntegerLiteralConvertible 383 | let json: JSON = 12345 384 | ``` 385 | 386 | ```swift 387 | //BooleanLiteralConvertible 388 | let json: JSON = true 389 | ``` 390 | 391 | ```swift 392 | //FloatLiteralConvertible 393 | let json: JSON = 2.8765 394 | ``` 395 | 396 | ```swift 397 | //DictionaryLiteralConvertible 398 | let json: JSON = ["I":"am", "a":"json"] 399 | ``` 400 | 401 | ```swift 402 | //ArrayLiteralConvertible 403 | let json: JSON = ["I", "am", "a", "json"] 404 | ``` 405 | 406 | ```swift 407 | //NilLiteralConvertible 408 | let json: JSON = nil 409 | ``` 410 | 411 | ```swift 412 | //With subscript in array 413 | var json: JSON = [1,2,3] 414 | json[0] = 100 415 | json[1] = 200 416 | json[2] = 300 417 | json[999] = 300 //Don't worry, nothing will happen 418 | ``` 419 | 420 | ```swift 421 | //With subscript in dictionary 422 | var json: JSON = ["name": "Jack", "age": 25] 423 | json["name"] = "Mike" 424 | json["age"] = "25" //It's OK to set String 425 | json["address"] = "L.A." // Add the "address": "L.A." in json 426 | ``` 427 | 428 | ```swift 429 | //Array & Dictionary 430 | var json: JSON = ["name": "Jack", "age": 25, "list": ["a", "b", "c", ["what": "this"]]] 431 | json["list"][3]["what"] = "that" 432 | json["list",3,"what"] = "that" 433 | let path: [JSONSubscriptType] = ["list",3,"what"] 434 | json[path] = "that" 435 | ``` 436 | 437 | ```swift 438 | //With other JSON objects 439 | let user: JSON = ["username" : "Steve", "password": "supersecurepassword"] 440 | let auth: JSON = [ 441 | "user": user.object //use user.object instead of just user 442 | "apikey": "supersecretapitoken" 443 | ] 444 | ``` 445 | 446 | #### Merging 447 | 448 | It is possible to merge one JSON into another JSON. Merging a JSON into another JSON adds all non existing values to the original JSON which are only present in the `other` JSON. 449 | 450 | If both JSONs contain a value for the same key, _mostly_ this value gets overwritten in the original JSON, but there are two cases where it provides some special treatment: 451 | 452 | - In case of both values being a `JSON.Type.array` the values form the array found in the `other` JSON getting appended to the original JSON's array value. 453 | - In case of both values being a `JSON.Type.dictionary` both JSON-values are getting merged the same way the encapsulating JSON is merged. 454 | 455 | In case, where two fields in a JSON have a different types, the value will get always overwritten. 456 | 457 | There are two different fashions for merging: `merge` modifies the original JSON, whereas `merged` works non-destructively on a copy. 458 | 459 | ```swift 460 | let original: JSON = [ 461 | "first_name": "John", 462 | "age": 20, 463 | "skills": ["Coding", "Reading"], 464 | "address": [ 465 | "street": "Front St", 466 | "zip": "12345", 467 | ] 468 | ] 469 | 470 | let update: JSON = [ 471 | "last_name": "Doe", 472 | "age": 21, 473 | "skills": ["Writing"], 474 | "address": [ 475 | "zip": "12342", 476 | "city": "New York City" 477 | ] 478 | ] 479 | 480 | let updated = original.merge(with: update) 481 | // [ 482 | // "first_name": "John", 483 | // "last_name": "Doe", 484 | // "age": 21, 485 | // "skills": ["Coding", "Reading", "Writing"], 486 | // "address": [ 487 | // "street": "Front St", 488 | // "zip": "12342", 489 | // "city": "New York City" 490 | // ] 491 | // ] 492 | ``` 493 | 494 | ## String representation 495 | There are two options available: 496 | - use the default Swift one 497 | - use a custom one that will handle optionals well and represent `nil` as `"null"`: 498 | ```swift 499 | let dict = ["1":2, "2":"two", "3": nil] as [String: Any?] 500 | let json = JSON(dict) 501 | let representation = json.rawString(options: [.castNilToNSNull: true]) 502 | // representation is "{\"1\":2,\"2\":\"two\",\"3\":null}", which represents {"1":2,"2":"two","3":null} 503 | ``` 504 | 505 | ## Work with Alamofire 506 | 507 | SwiftyJSON nicely wraps the result of the Alamofire JSON response handler: 508 | 509 | ```swift 510 | Alamofire.request(url, method: .get).validate().responseJSON { response in 511 | switch response.result { 512 | case .success(let value): 513 | let json = JSON(value) 514 | print("JSON: \(json)") 515 | case .failure(let error): 516 | print(error) 517 | } 518 | } 519 | ``` 520 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/Alamofire/Alamofire-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Alamofire : NSObject 3 | @end 4 | @implementation PodsDummy_Alamofire 5 | @end 6 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/Alamofire/Alamofire-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /POP/Negotiate/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 | -------------------------------------------------------------------------------- /POP/Negotiate/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 | -------------------------------------------------------------------------------- /POP/Negotiate/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 | -------------------------------------------------------------------------------- /POP/Negotiate/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.3.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/Pods-Negotiate/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 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/Pods-Negotiate/Pods-Negotiate-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 | ## SwiftyJSON 28 | 29 | The MIT License (MIT) 30 | 31 | Copyright (c) 2016 Ruoyu Fu 32 | 33 | Permission is hereby granted, free of charge, to any person obtaining a copy 34 | of this software and associated documentation files (the "Software"), to deal 35 | in the Software without restriction, including without limitation the rights 36 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 37 | copies of the Software, and to permit persons to whom the Software is 38 | furnished to do so, subject to the following conditions: 39 | 40 | The above copyright notice and this permission notice shall be included in 41 | all copies or substantial portions of the Software. 42 | 43 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 45 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 46 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 47 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 48 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 49 | THE SOFTWARE. 50 | 51 | Generated by CocoaPods - https://cocoapods.org 52 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/Pods-Negotiate/Pods-Negotiate-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 | The MIT License (MIT) 47 | 48 | Copyright (c) 2016 Ruoyu Fu 49 | 50 | Permission is hereby granted, free of charge, to any person obtaining a copy 51 | of this software and associated documentation files (the "Software"), to deal 52 | in the Software without restriction, including without limitation the rights 53 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 54 | copies of the Software, and to permit persons to whom the Software is 55 | furnished to do so, subject to the following conditions: 56 | 57 | The above copyright notice and this permission notice shall be included in 58 | all copies or substantial portions of the Software. 59 | 60 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 61 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 62 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 63 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 64 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 65 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 66 | THE SOFTWARE. 67 | 68 | License 69 | MIT 70 | Title 71 | SwiftyJSON 72 | Type 73 | PSGroupSpecifier 74 | 75 | 76 | FooterText 77 | Generated by CocoaPods - https://cocoapods.org 78 | Title 79 | 80 | Type 81 | PSGroupSpecifier 82 | 83 | 84 | StringsTable 85 | Acknowledgements 86 | Title 87 | Acknowledgements 88 | 89 | 90 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/Pods-Negotiate/Pods-Negotiate-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Negotiate : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Negotiate 5 | @end 6 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/Pods-Negotiate/Pods-Negotiate-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/SwiftyJSON/SwiftyJSON.framework" 89 | fi 90 | if [[ "$CONFIGURATION" == "Release" ]]; then 91 | install_framework "$BUILT_PRODUCTS_DIR/Alamofire/Alamofire.framework" 92 | install_framework "$BUILT_PRODUCTS_DIR/SwiftyJSON/SwiftyJSON.framework" 93 | fi 94 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/Pods-Negotiate/Pods-Negotiate-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 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/Pods-Negotiate/Pods-Negotiate-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double Pods_NegotiateVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char Pods_NegotiateVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/Pods-Negotiate/Pods-Negotiate.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/SwiftyJSON" 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/SwiftyJSON/SwiftyJSON.framework/Headers" 7 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "SwiftyJSON" 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 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/Pods-Negotiate/Pods-Negotiate.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Negotiate { 2 | umbrella header "Pods-Negotiate-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/Pods-Negotiate/Pods-Negotiate.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/SwiftyJSON" 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/SwiftyJSON/SwiftyJSON.framework/Headers" 7 | OTHER_LDFLAGS = $(inherited) -framework "Alamofire" -framework "SwiftyJSON" 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 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/SwiftyJSON/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.4 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_SwiftyJSON : NSObject 3 | @end 4 | @implementation PodsDummy_SwiftyJSON 5 | @end 6 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/SwiftyJSON/SwiftyJSON-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double SwiftyJSONVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char SwiftyJSONVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/SwiftyJSON/SwiftyJSON.modulemap: -------------------------------------------------------------------------------- 1 | framework module SwiftyJSON { 2 | umbrella header "SwiftyJSON-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /POP/Negotiate/Pods/Target Support Files/SwiftyJSON/SwiftyJSON.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/SwiftyJSON 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 | SWIFT_VERSION = 3.0 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # YYGRegular 2 | 3 | ``` 4 | 我是: 语歌 5 | 6 | ``` 7 | [个人博客](http://aiyinyu.com:8090/) 8 | 9 | 10 | 11 | 12 | It is a regular expression used on iOS, which implement by Swift 13 | 14 | 这是一个基于swift快捷开发的扩展类,目前的涵盖内容包括详细打印,正则表达式,会经常维护 15 | 16 | 17 | ##直接把 Category 文件夹拖转到工程里面就行 18 | ###1.打印的方法,及简单介绍 19 | 20 | | 符号 | 类型 | 描述 | 21 | | --- | --- | --- | 22 | | #file | String | 包含这个符号的文件路径 | 23 | | #line | Int | 符号出现的行号 | 24 | | #column | Int | 符号出现的类 | 25 | | #function | String | 包含这个符号的方法名字 | 26 | 27 | 28 | ``` 29 | public func printLogDebug(_ message: T, 30 | file: String = #file, 31 | method: String = #function, 32 | line: Int = #line 33 | ) 34 | { 35 | #if DEBUG 36 | print("------------------\(line) lineBegin-------------------------\n类名称: \((file as NSString).lastPathComponent)\n方法名: \(method)\n信息: \(message)\n------------------\(line) line End-------------------------") 37 | #endif 38 | } 39 | ``` 40 | 41 | ###### 调用 42 | > 43 | ``` 44 | 直接调用打印: 45 | printLogDebug("内容") 46 | ``` 47 | > 48 | 49 | 50 | 51 | ###在 Release 版本中会自动关闭掉向控制台的输出。 52 | ***打印效果如下:*** 53 | 54 | 55 | 56 | ``` 57 | ------------------(*行号*) lineBegin------------------------- 58 | 类名称: ***.swift 59 | 方法名: *** 60 | 信息: ***打印的内容*** 61 | ------------------(*行号*) line End------------------------- 62 | ``` 63 | ###关于public的使用看下表 64 | | 名称 | 控制级(1-5,5最高) | 解释 | 65 | | :-: | :-: | :-: | 66 | | private | 1 | 只能在当前作用域中使用 | 67 | | fileprivate | 2 | 只能在当前文件夹中使用 | 68 | | internal | 3默认的 | target中的其他代码访问 | 69 | | public | 4 | 为其他开发者开发库使用 | 70 | | open | 5 | 为其他开发者开发库使用被open标记 的才能在其他库中重写 | 71 | : 72 | 73 | 74 | ### 2.正则表达式用法 75 | 示例: 76 | > 77 | #####因为Swift支持重载操作符, 这个用 **=~** 来判断是否符合,关于=~ 功能及符号的定义,自己去代码里面找吧!!! 78 | > 79 | ``` 80 | if "13146492969@sina.cn" =~ mail { 81 | printLogDebug("^_^") 82 | } else { 83 | printLogDebug("~~~~(>_<)~~~~") 84 | } 85 | /// 自定义的匹配格式判断是否是手机号 86 | let isIphoneNum: String = "1\\d{10}" 87 | if "13146492969" =~ isIphoneNum { 88 | printLogDebug("^_^") 89 | } else { 90 | printLogDebug("~~~~(>_<)~~~~") 91 | } 92 | ``` 93 | 94 | ####定义了操作符的优先级: 95 | `precedencegroup` 96 | ####定义了相同操作符出现的结合顺序 97 | `associativity` 98 | ####表示前后都是输入 99 | `infix` 100 | 101 | ####相关正则匹配的写法,有想知道更详细的写法 请移步: [正则表达式学习](http://deerchao.net/tutorials/regex/common.htm) 102 | ###以下给出基本的写法。 103 | **不足之处,烦请指出** 104 | 105 | ``` 106 | 1./// 邮箱匹配 107 | let mail: String = "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$" 108 | 109 | 2./// 匹配用户名 字面或者数字组合 4到16位 110 | let Username: String = "^[a-z0-9_-]{4,16}$" 111 | 112 | 3./// 匹配密码 字面加下划线,6到18位 113 | let Password: String = "^[a-z0-9_-]{6,18}$" 114 | 115 | 4./// 匹配16进制 116 | let HexValue: String = "^#?([a-f0-9]{6}|[a-f0-9]{3})$" 117 | 118 | 5.///内容带分割符号 “Anne-Blair” 119 | let Slug: String = "^[a-z0-9-]+$" 120 | 121 | 6./// 匹配URL 122 | let isURL: String = "^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$" 123 | 124 | 7./// 匹配IP地址 125 | let IPAddress: String = "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$" 126 | 127 | 8./// 是HTML
内容<\center> 符合 128 | let HTMLTag: String = "^<([a-z]+)([^<]+)*(?:>(.*)<\\/\\1>|\\s+\\/>)$" 129 | 130 | 9./// 日期(年-月-日) 131 | let isDate1: String = "(\\d{4}|\\d{2})-((1[0-2])|(0?[1-9]))-(([12][0-9])|(3[01])|(0?[1-9]))" 132 | 133 | 10./// 日期(月/日/年) 134 | let isDate2: String = "((1[0-2])|(0?[1-9]))/(([12][0-9])|(3[01])|(0?[1-9]))/(\\d{4}|\\d{2})" 135 | 136 | 11./// 时间(小时:分钟, 24小时制) 137 | let TimeFormat: String = "((1|0?)[0-9]|2[0-3]):([0-5][0-9])" 138 | 139 | 12./// 是汉字 140 | let isChinese: String = "[\\u4e00-\\u9fa5]" 141 | 142 | 13./// 中文及全角标点符号(字符) 143 | let ChineseParagraph: String = "[\\u3000-\\u301e\\ufe10-\\ufe19\\ufe30-\\ufe44\\ufe50-\\ufe6b\\uff01-\\uffee]" 144 | 145 | 14./// 中国大陆固定电话号码 146 | let fixedLineTelephone: String = "(\\d{4}-|\\d{3}-)?(\\d{8}|\\d{7})" 147 | 148 | 15./// 中国大陆身份证号(15位或18位) 149 | let IdNum: String = "\\d{15}(\\d\\d[0-9xX])?" 150 | 151 | 16./// 手机号 152 | let isIphoneNum: String = "1\\d{10}" 153 | 154 | 17./// 邮政编码 155 | let zipCode: String = "[1-9]\\d{5}" 156 | ``` 157 | 158 | ##新增加一些方法的扩展。如:UIView的扩展,富文本的扩展,UIColor的扩展,线程安全使用的扩展 159 | ###3.UIView的一些扩展 160 | #### 主要是方便直接对视图控件x,y等等一系列的操作 161 | #### 这个比较简单,不做介绍,主要是 set,get,集成后直接用就行 162 | 163 | ``` 164 | extension UIView { 165 | 166 | var x: CGFloat { 167 | get { 168 | return frame.origin.x 169 | } 170 | set { 171 | frame = CGRect(x: newValue, y: frame.origin.y, width: frame.width, height: frame.height) 172 | } 173 | } 174 | ........................ 175 | ``` 176 | 177 | ### 4.线程安全操作 178 | #### 在Oc中为了防止多线程中对某些资源的安全访问 引用了 179 | `@synchronized`的操作,更多的关于多线程的知识 [点我](https://www.objccn.io/issue-2-1/),这里大量篇幅的描述,会使你得到更多的收获。这里不做陈述 180 | 181 | #### 在Swift中已经移除了`synchronized` 的使用,相应的 我们可以直接使用: 182 | `objc_sync_enter` 183 | ///资源的操作 184 | `objc_sync_exit` 185 | #### 结合闭包的使用可以直接这样使用 186 | ``` 187 | public func synchronized(_ lock: AnyObject, closure: () -> ()) { 188 | objc_sync_enter(lock) 189 | closure() 190 | objc_sync_exit(lock) 191 | } 192 | ``` 193 | #### 相应的执行的时候你可以这样: 194 | ``` 195 | var test = 0 196 | synchronized(test as AnyObject) { 197 | test = 1 // test 在该作用域不会被其他线程改变 198 | print(test) 199 | } 200 | /// 或者这样 201 | synchronized(test as AnyObject, closure: { 202 | print(test) // test 在该作用域不会被其他线程改变 203 | }) 204 | ``` 205 | #### 这样你就可以愉快的使用了 206 | 207 | ### 5.对UIColor的扩展 208 | #### 都知道Xcode在8.0以后可以直接在代码中使用颜色编辑器,图片预览。这样大大的节省了我们的开发效率 209 | #### 而在于有时候的习惯的使用上来说,可能或多或少还有用代码来操作的,这里带给大家在使用代码的时候的一些方便 210 | ##### 有时候在开发的过程中UI给的标注是 0xCE0755 这样的颜色标注,那么我们有时候就需要转换,当然在颜色编辑器里面是可以直接使用的。 211 | > 转换如下: 212 | 213 | ``` 214 | public extension UIColor { 215 | 216 | /// Init color without divide 255.0 217 | /// 218 | /// - Parameters: 219 | /// - r: (0 ~ 255) red 220 | /// - g: (0 ~ 255) green 221 | /// - b: (0 ~ 255) blue 222 | /// - a: (0 ~ 1) alpha 223 | convenience init(r: Int, g: Int, b: Int, a: CGFloat) { 224 | self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: a) 225 | } 226 | 227 | /// Init color without divide 255.0 228 | /// 229 | /// - Parameters: 230 | /// - r: (0 ~ 255) red 231 | /// - g: (0 ~ 255) green 232 | /// - b: (0 ~ 1) alpha 233 | convenience init(r: Int, g: Int, b: Int) { 234 | self.init(r: r, g: g, b: b, a: 1) 235 | } 236 | 237 | /// Init color with hex code 238 | /// 239 | /// - Parameter hex: hex code (eg. 0x00eeee) 240 | convenience init(hex: Int) { 241 | self.init(r: (hex & 0xff0000) >> 16, g: (hex & 0xff00) >> 8, b: (hex & 0xff), a: 1) 242 | } 243 | 244 | } 245 | ``` 246 | #### 这里要说的是主要原理就是: 先通过&运算,取得相应的颜色位,然后通过左移相应的位数来进行换算。这里就不多说了。[传送门](https://zh.wikipedia.org/wiki/%E4%BD%8D%E6%93%8D%E4%BD%9C) 247 | 248 | ### 6.富文本的一些操作,工程中非常清楚的介绍了使用,这里不做陈述了。 249 | ##### 科学计数法转换 250 | ##### 人民币的金额转换 251 | 252 | ### 7.对String的扩展,进行截取,插入操作 253 | ``` 254 | extension String { 255 | /// 截取第一个到第任意位置 256 | /// 257 | /// - Parameter end: 结束的位值 258 | /// - Returns: 截取后的字符串 259 | func stringCut(end: Int) ->String{ 260 | printLogDebug(self.characters.count) 261 | if !(end < characters.count) { return "截取超出范围" } 262 | let sInde = index(startIndex, offsetBy: end) 263 | return substring(to: sInde) 264 | } 265 | 266 | /// 截取人任意位置到结束 267 | /// 268 | /// - Parameter end: 269 | /// - Returns: 截取后的字符串 270 | func stringCutToEnd(star: Int) -> String { 271 | if !(star < characters.count) { return "截取超出范围" } 272 | let sRang = index(startIndex, offsetBy: star).. String { 283 | if !(locat < characters.count) { return "截取超出范围" } 284 | let str1 = stringCut(end: locat) 285 | let str2 = stringCutToEnd(star: locat) 286 | return str1 + content + str2 287 | } 288 | } 289 | ``` 290 | 291 | ### 8.延时使用,异步延时,主线程执行 292 | >使用: 293 | 294 | ``` 295 | let sleep = delay(0.7) { 296 | /// 执行代码 297 | } 298 | ``` 299 | > 使用过程中不想执行了 300 | 301 | ``` 302 | cancel(sleep) 303 | 304 | ``` 305 | 306 | ##### 源码如下: 307 | ``` 308 | //MARK: 延时使用 ____________________________________________________________________________________________________ 309 | 310 | typealias Task = (_ cancel : Bool) -> Void 311 | 312 | func delay(_ time: TimeInterval, task: @escaping ()->()) -> Task? { 313 | 314 | func dispatch_later(block: @escaping ()->()) { 315 | let t = DispatchTime.now() + time 316 | DispatchQueue.main.asyncAfter(deadline: t, execute: block) 317 | } 318 | 319 | var closure: (()->Void)? = task 320 | var result: Task? 321 | 322 | let delayedClosure: Task = { 323 | cancel in 324 | if let internalClosure = closure { 325 | if (cancel == false) { 326 | DispatchQueue.main.async(execute: internalClosure) 327 | } 328 | } 329 | closure = nil 330 | result = nil 331 | } 332 | 333 | result = delayedClosure 334 | 335 | dispatch_later { 336 | if let delayedClosure = result { 337 | delayedClosure(false) 338 | } 339 | } 340 | return result 341 | } 342 | 343 | func cancel(_ task: Task?) { 344 | task?(true) 345 | } 346 | ``` 347 | 348 | ### 更新继续,如果您觉得对你有帮助 那就来个 [star](https://github.com/AnneBlair/YYGRegular/stargazers) 349 | 350 | -------------------------------------------------------------------------------- /YYGRegular.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "YYGRegular" 3 | s.version = "1.0.0" 4 | s.summary = "The package of useful tools, include categories and classes" 5 | s.homepage = "http://blog.aiyinyu.com" 6 | s.license = "MIT" 7 | s.authors = { 'tangjr' => 'sirbliar@gmail.com'} 8 | s.platform = :ios, "8.0" 9 | s.source = { :git => "https://github.com/AnneBlair/YYGRegular.git", :tag => s.version } 10 | 11 | s.source_files = ["YYGRegular/*.swift"] 12 | s.pod_target_xcconfig = { 'SWIFT_VERSION' => '3.0' } 13 | s.requires_arc = true 14 | end 15 | -------------------------------------------------------------------------------- /YYGRegular.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C0A4DFFC1F60541300578E2C /* YYGRegular.h in Headers */ = {isa = PBXBuildFile; fileRef = C0A4DFFA1F60541300578E2C /* YYGRegular.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | C0A4E04C1F6191F300578E2C /* YYGText.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0A4E0461F6191F300578E2C /* YYGText.swift */; }; 12 | C0A4E04D1F6191F300578E2C /* YYGRegular.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0A4E0471F6191F300578E2C /* YYGRegular.swift */; }; 13 | C0A4E04E1F6191F300578E2C /* SwitchSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0A4E0481F6191F300578E2C /* SwitchSegue.swift */; }; 14 | C0A4E04F1F6191F300578E2C /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0A4E0491F6191F300578E2C /* UIView.swift */; }; 15 | C0A4E0501F6191F300578E2C /* YYGcategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0A4E04A1F6191F300578E2C /* YYGcategory.swift */; }; 16 | C0A4E0511F6191F300578E2C /* arrayDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0A4E04B1F6191F300578E2C /* arrayDataSource.swift */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | C0A4DFF71F60541300578E2C /* YYGRegular.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = YYGRegular.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | C0A4DFFA1F60541300578E2C /* YYGRegular.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YYGRegular.h; sourceTree = ""; }; 22 | C0A4DFFB1F60541300578E2C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 23 | C0A4E0461F6191F300578E2C /* YYGText.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YYGText.swift; sourceTree = ""; }; 24 | C0A4E0471F6191F300578E2C /* YYGRegular.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YYGRegular.swift; sourceTree = ""; }; 25 | C0A4E0481F6191F300578E2C /* SwitchSegue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwitchSegue.swift; sourceTree = ""; }; 26 | C0A4E0491F6191F300578E2C /* UIView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = ""; }; 27 | C0A4E04A1F6191F300578E2C /* YYGcategory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YYGcategory.swift; sourceTree = ""; }; 28 | C0A4E04B1F6191F300578E2C /* arrayDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = arrayDataSource.swift; sourceTree = ""; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | C0A4DFF31F60541300578E2C /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | C0A4DFED1F60541300578E2C = { 43 | isa = PBXGroup; 44 | children = ( 45 | C0A4DFF91F60541300578E2C /* YYGRegular */, 46 | C0A4DFF81F60541300578E2C /* Products */, 47 | ); 48 | sourceTree = ""; 49 | }; 50 | C0A4DFF81F60541300578E2C /* Products */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | C0A4DFF71F60541300578E2C /* YYGRegular.framework */, 54 | ); 55 | name = Products; 56 | sourceTree = ""; 57 | }; 58 | C0A4DFF91F60541300578E2C /* YYGRegular */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | C0A4DFFA1F60541300578E2C /* YYGRegular.h */, 62 | C0A4E0461F6191F300578E2C /* YYGText.swift */, 63 | C0A4E0471F6191F300578E2C /* YYGRegular.swift */, 64 | C0A4E0481F6191F300578E2C /* SwitchSegue.swift */, 65 | C0A4E0491F6191F300578E2C /* UIView.swift */, 66 | C0A4E04A1F6191F300578E2C /* YYGcategory.swift */, 67 | C0A4E04B1F6191F300578E2C /* arrayDataSource.swift */, 68 | C0A4DFFB1F60541300578E2C /* Info.plist */, 69 | ); 70 | path = YYGRegular; 71 | sourceTree = ""; 72 | }; 73 | /* End PBXGroup section */ 74 | 75 | /* Begin PBXHeadersBuildPhase section */ 76 | C0A4DFF41F60541300578E2C /* Headers */ = { 77 | isa = PBXHeadersBuildPhase; 78 | buildActionMask = 2147483647; 79 | files = ( 80 | C0A4DFFC1F60541300578E2C /* YYGRegular.h in Headers */, 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | /* End PBXHeadersBuildPhase section */ 85 | 86 | /* Begin PBXNativeTarget section */ 87 | C0A4DFF61F60541300578E2C /* YYGRegular */ = { 88 | isa = PBXNativeTarget; 89 | buildConfigurationList = C0A4DFFF1F60541300578E2C /* Build configuration list for PBXNativeTarget "YYGRegular" */; 90 | buildPhases = ( 91 | C0A4DFF21F60541300578E2C /* Sources */, 92 | C0A4DFF31F60541300578E2C /* Frameworks */, 93 | C0A4DFF41F60541300578E2C /* Headers */, 94 | C0A4DFF51F60541300578E2C /* Resources */, 95 | ); 96 | buildRules = ( 97 | ); 98 | dependencies = ( 99 | ); 100 | name = YYGRegular; 101 | productName = YYGRegular; 102 | productReference = C0A4DFF71F60541300578E2C /* YYGRegular.framework */; 103 | productType = "com.apple.product-type.framework"; 104 | }; 105 | /* End PBXNativeTarget section */ 106 | 107 | /* Begin PBXProject section */ 108 | C0A4DFEE1F60541300578E2C /* Project object */ = { 109 | isa = PBXProject; 110 | attributes = { 111 | LastUpgradeCheck = 0830; 112 | ORGANIZATIONNAME = blog.aiyinyu.com; 113 | TargetAttributes = { 114 | C0A4DFF61F60541300578E2C = { 115 | CreatedOnToolsVersion = 8.3.3; 116 | LastSwiftMigration = 0830; 117 | ProvisioningStyle = Automatic; 118 | }; 119 | }; 120 | }; 121 | buildConfigurationList = C0A4DFF11F60541300578E2C /* Build configuration list for PBXProject "YYGRegular" */; 122 | compatibilityVersion = "Xcode 3.2"; 123 | developmentRegion = English; 124 | hasScannedForEncodings = 0; 125 | knownRegions = ( 126 | en, 127 | ); 128 | mainGroup = C0A4DFED1F60541300578E2C; 129 | productRefGroup = C0A4DFF81F60541300578E2C /* Products */; 130 | projectDirPath = ""; 131 | projectRoot = ""; 132 | targets = ( 133 | C0A4DFF61F60541300578E2C /* YYGRegular */, 134 | ); 135 | }; 136 | /* End PBXProject section */ 137 | 138 | /* Begin PBXResourcesBuildPhase section */ 139 | C0A4DFF51F60541300578E2C /* Resources */ = { 140 | isa = PBXResourcesBuildPhase; 141 | buildActionMask = 2147483647; 142 | files = ( 143 | ); 144 | runOnlyForDeploymentPostprocessing = 0; 145 | }; 146 | /* End PBXResourcesBuildPhase section */ 147 | 148 | /* Begin PBXSourcesBuildPhase section */ 149 | C0A4DFF21F60541300578E2C /* Sources */ = { 150 | isa = PBXSourcesBuildPhase; 151 | buildActionMask = 2147483647; 152 | files = ( 153 | C0A4E0501F6191F300578E2C /* YYGcategory.swift in Sources */, 154 | C0A4E04F1F6191F300578E2C /* UIView.swift in Sources */, 155 | C0A4E04D1F6191F300578E2C /* YYGRegular.swift in Sources */, 156 | C0A4E04E1F6191F300578E2C /* SwitchSegue.swift in Sources */, 157 | C0A4E0511F6191F300578E2C /* arrayDataSource.swift in Sources */, 158 | C0A4E04C1F6191F300578E2C /* YYGText.swift in Sources */, 159 | ); 160 | runOnlyForDeploymentPostprocessing = 0; 161 | }; 162 | /* End PBXSourcesBuildPhase section */ 163 | 164 | /* Begin XCBuildConfiguration section */ 165 | C0A4DFFD1F60541300578E2C /* Debug */ = { 166 | isa = XCBuildConfiguration; 167 | buildSettings = { 168 | ALWAYS_SEARCH_USER_PATHS = NO; 169 | CLANG_ANALYZER_NONNULL = YES; 170 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 171 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 172 | CLANG_CXX_LIBRARY = "libc++"; 173 | CLANG_ENABLE_MODULES = YES; 174 | CLANG_ENABLE_OBJC_ARC = YES; 175 | CLANG_WARN_BOOL_CONVERSION = YES; 176 | CLANG_WARN_CONSTANT_CONVERSION = YES; 177 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 178 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 179 | CLANG_WARN_EMPTY_BODY = YES; 180 | CLANG_WARN_ENUM_CONVERSION = YES; 181 | CLANG_WARN_INFINITE_RECURSION = YES; 182 | CLANG_WARN_INT_CONVERSION = YES; 183 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 184 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 185 | CLANG_WARN_UNREACHABLE_CODE = YES; 186 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 187 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 188 | COPY_PHASE_STRIP = NO; 189 | CURRENT_PROJECT_VERSION = 1; 190 | DEBUG_INFORMATION_FORMAT = dwarf; 191 | ENABLE_STRICT_OBJC_MSGSEND = YES; 192 | ENABLE_TESTABILITY = YES; 193 | GCC_C_LANGUAGE_STANDARD = gnu99; 194 | GCC_DYNAMIC_NO_PIC = NO; 195 | GCC_NO_COMMON_BLOCKS = YES; 196 | GCC_OPTIMIZATION_LEVEL = 0; 197 | GCC_PREPROCESSOR_DEFINITIONS = ( 198 | "DEBUG=1", 199 | "$(inherited)", 200 | ); 201 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 202 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 203 | GCC_WARN_UNDECLARED_SELECTOR = YES; 204 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 205 | GCC_WARN_UNUSED_FUNCTION = YES; 206 | GCC_WARN_UNUSED_VARIABLE = YES; 207 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 208 | MTL_ENABLE_DEBUG_INFO = YES; 209 | ONLY_ACTIVE_ARCH = YES; 210 | SDKROOT = iphoneos; 211 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 212 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 213 | TARGETED_DEVICE_FAMILY = "1,2"; 214 | VERSIONING_SYSTEM = "apple-generic"; 215 | VERSION_INFO_PREFIX = ""; 216 | }; 217 | name = Debug; 218 | }; 219 | C0A4DFFE1F60541300578E2C /* Release */ = { 220 | isa = XCBuildConfiguration; 221 | buildSettings = { 222 | ALWAYS_SEARCH_USER_PATHS = NO; 223 | CLANG_ANALYZER_NONNULL = YES; 224 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 225 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 226 | CLANG_CXX_LIBRARY = "libc++"; 227 | CLANG_ENABLE_MODULES = YES; 228 | CLANG_ENABLE_OBJC_ARC = YES; 229 | CLANG_WARN_BOOL_CONVERSION = YES; 230 | CLANG_WARN_CONSTANT_CONVERSION = YES; 231 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 232 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 233 | CLANG_WARN_EMPTY_BODY = YES; 234 | CLANG_WARN_ENUM_CONVERSION = YES; 235 | CLANG_WARN_INFINITE_RECURSION = YES; 236 | CLANG_WARN_INT_CONVERSION = YES; 237 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 238 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 239 | CLANG_WARN_UNREACHABLE_CODE = YES; 240 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 241 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 242 | COPY_PHASE_STRIP = NO; 243 | CURRENT_PROJECT_VERSION = 1; 244 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 245 | ENABLE_NS_ASSERTIONS = NO; 246 | ENABLE_STRICT_OBJC_MSGSEND = YES; 247 | GCC_C_LANGUAGE_STANDARD = gnu99; 248 | GCC_NO_COMMON_BLOCKS = YES; 249 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 250 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 251 | GCC_WARN_UNDECLARED_SELECTOR = YES; 252 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 253 | GCC_WARN_UNUSED_FUNCTION = YES; 254 | GCC_WARN_UNUSED_VARIABLE = YES; 255 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 256 | MTL_ENABLE_DEBUG_INFO = NO; 257 | SDKROOT = iphoneos; 258 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 259 | TARGETED_DEVICE_FAMILY = "1,2"; 260 | VALIDATE_PRODUCT = YES; 261 | VERSIONING_SYSTEM = "apple-generic"; 262 | VERSION_INFO_PREFIX = ""; 263 | }; 264 | name = Release; 265 | }; 266 | C0A4E0001F60541300578E2C /* Debug */ = { 267 | isa = XCBuildConfiguration; 268 | buildSettings = { 269 | CLANG_ENABLE_MODULES = YES; 270 | CODE_SIGN_IDENTITY = ""; 271 | DEFINES_MODULE = YES; 272 | DEVELOPMENT_TEAM = ""; 273 | DYLIB_COMPATIBILITY_VERSION = 1; 274 | DYLIB_CURRENT_VERSION = 1; 275 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 276 | INFOPLIST_FILE = YYGRegular/Info.plist; 277 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 278 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 279 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 280 | PRODUCT_BUNDLE_IDENTIFIER = "com.eco-chain.YYGRegular"; 281 | PRODUCT_NAME = "$(TARGET_NAME)"; 282 | SKIP_INSTALL = YES; 283 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 284 | SWIFT_VERSION = 3.0; 285 | }; 286 | name = Debug; 287 | }; 288 | C0A4E0011F60541300578E2C /* Release */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | CLANG_ENABLE_MODULES = YES; 292 | CODE_SIGN_IDENTITY = ""; 293 | DEFINES_MODULE = YES; 294 | DEVELOPMENT_TEAM = ""; 295 | DYLIB_COMPATIBILITY_VERSION = 1; 296 | DYLIB_CURRENT_VERSION = 1; 297 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 298 | INFOPLIST_FILE = YYGRegular/Info.plist; 299 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 300 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 301 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 302 | PRODUCT_BUNDLE_IDENTIFIER = "com.eco-chain.YYGRegular"; 303 | PRODUCT_NAME = "$(TARGET_NAME)"; 304 | SKIP_INSTALL = YES; 305 | SWIFT_VERSION = 3.0; 306 | }; 307 | name = Release; 308 | }; 309 | /* End XCBuildConfiguration section */ 310 | 311 | /* Begin XCConfigurationList section */ 312 | C0A4DFF11F60541300578E2C /* Build configuration list for PBXProject "YYGRegular" */ = { 313 | isa = XCConfigurationList; 314 | buildConfigurations = ( 315 | C0A4DFFD1F60541300578E2C /* Debug */, 316 | C0A4DFFE1F60541300578E2C /* Release */, 317 | ); 318 | defaultConfigurationIsVisible = 0; 319 | defaultConfigurationName = Release; 320 | }; 321 | C0A4DFFF1F60541300578E2C /* Build configuration list for PBXNativeTarget "YYGRegular" */ = { 322 | isa = XCConfigurationList; 323 | buildConfigurations = ( 324 | C0A4E0001F60541300578E2C /* Debug */, 325 | C0A4E0011F60541300578E2C /* Release */, 326 | ); 327 | defaultConfigurationIsVisible = 0; 328 | defaultConfigurationName = Release; 329 | }; 330 | /* End XCConfigurationList section */ 331 | }; 332 | rootObject = C0A4DFEE1F60541300578E2C /* Project object */; 333 | } 334 | -------------------------------------------------------------------------------- /YYGRegular.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /YYGRegular/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 | -------------------------------------------------------------------------------- /YYGRegular/SwitchSegue.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwitchSegue.swift 3 | // Aplan 4 | // 5 | // Created by 区块国际-yin on 2017/5/4. 6 | // Copyright © 2017年 blog.aiyinyu.com. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol SegueHandelr { 12 | associatedtype SegueIdentifier: RawRepresentable 13 | } 14 | 15 | extension SegueHandelr where Self: UIViewController, SegueIdentifier.RawValue == String { 16 | func segueIdentifier(for segue: UIStoryboardSegue) -> SegueIdentifier { 17 | guard let identifier = segue.identifier, let segueIdentifier = SegueIdentifier(rawValue: identifier) else { fatalError("UnKnown segue: \(segue)") } 18 | return segueIdentifier 19 | } 20 | 21 | func performSegue(withIdentifier segueIdentifier: SegueIdentifier) { 22 | performSegue(withIdentifier: segueIdentifier.rawValue, sender: nil) 23 | } 24 | } 25 | // 26 | //func viewController(forStoryboardName: String) -> UIViewController { 27 | // return UIStoryboard(name: forStoryboardName, bundle: nil).instantiateInitialViewController()! 28 | //} 29 | // 30 | //class TemplateImageView: UIImageView { 31 | // @IBInspectable var templateImage: UIImage? { 32 | // didSet { 33 | // image = templateImage?.withRenderingMode(.alwaysTemplate) 34 | // } 35 | // } 36 | //} 37 | -------------------------------------------------------------------------------- /YYGRegular/UIView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView.swift 3 | // shopDemo 4 | // 5 | // Created by 区块国际-yin on 2017/4/19. 6 | // Copyright © 2017年 blog.aiyinyu.com. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public extension UIView { 12 | @IBInspectable public var cornerRadius: CGFloat { 13 | get { 14 | return layer.cornerRadius 15 | } 16 | 17 | set { 18 | layer.cornerRadius = newValue 19 | } 20 | } 21 | @IBInspectable public var shadowRadius: CGFloat { 22 | get { 23 | return layer.shadowRadius 24 | } 25 | 26 | set { 27 | layer.shadowRadius = newValue 28 | } 29 | } 30 | @IBInspectable public var shadowOpacity: Float { 31 | get { 32 | return layer.shadowOpacity 33 | } 34 | 35 | set { 36 | layer.shadowOpacity = newValue 37 | } 38 | } 39 | @IBInspectable public var shadowColor: UIColor? { 40 | get { 41 | return layer.shadowColor != nil ? UIColor(cgColor: layer.shadowColor!) : nil 42 | } 43 | 44 | set { 45 | layer.shadowColor = newValue?.cgColor 46 | } 47 | } 48 | @IBInspectable public var shadowOffset: CGSize { 49 | get { 50 | return layer.shadowOffset 51 | } 52 | 53 | set { 54 | layer.shadowOffset = newValue 55 | } 56 | } 57 | @IBInspectable public var zPosition: CGFloat { 58 | get { 59 | return layer.zPosition 60 | } 61 | 62 | set { 63 | layer.zPosition = newValue 64 | } 65 | } 66 | } 67 | 68 | //public func viewController(forStoryboardName: String) -> UIViewController { 69 | // return UIStoryboard(name: forStoryboardName, bundle: nil).instantiateInitialViewController()! 70 | //} 71 | // 72 | //class TemplateImageView: UIImageView { 73 | // @IBInspectable var templateImage: UIImage? { 74 | // didSet { 75 | // image = templateImage?.withRenderingMode(.alwaysTemplate) 76 | // } 77 | // } 78 | //} 79 | -------------------------------------------------------------------------------- /YYGRegular/YYGRegular.h: -------------------------------------------------------------------------------- 1 | // 2 | // YYGRegular.h 3 | // YYGRegular 4 | // 5 | // Created by AnneBlair on 2017/9/7. 6 | // Copyright © 2017年 blog.aiyinyu.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for YYGRegular. 12 | FOUNDATION_EXPORT double YYGRegularVersionNumber; 13 | 14 | //! Project version string for YYGRegular. 15 | FOUNDATION_EXPORT const unsigned char YYGRegularVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /YYGRegular/YYGRegular.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YYGRegular.swift 3 | // Ecshop 4 | // 5 | // Created by 区块国际-yin on 16/11/3. 6 | // Copyright © 2016年 区块国际-yin. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public struct RegexHelper { 12 | 13 | let regex: NSRegularExpression 14 | 15 | init(_ pattern: String) throws { 16 | try regex = NSRegularExpression(pattern: pattern, options: .caseInsensitive) 17 | } 18 | 19 | func match(_ input: String) -> Bool { 20 | let matches = regex.matches(in: input, options: [], range: NSMakeRange(0, input.utf16.count)) 21 | return matches.count > 0 22 | } 23 | 24 | } 25 | 26 | //swift 中新加操作符的时候需要先对其进行声明,告诉编译器这个符合其实是一个操作符合 27 | //precedencegroup 定义了一个操作符的优先级别 28 | precedencegroup MatchPrecedence { 29 | //associativity 定义了结合定律,多个同类操作符顺序出现的计算顺序 30 | associativity: none 31 | //higherThan 运算的优先级 32 | higherThan: DefaultPrecedence 33 | } 34 | 35 | //infix 表示定位的是一个中位操作符,意思是前后都是输入; 36 | //其他的修饰子还包括prefix和postfix 37 | infix operator =~: MatchPrecedence 38 | 39 | public func =~(object: String, template: String) -> Bool { 40 | do { 41 | return try RegexHelper(template).match(object) 42 | } catch _ { 43 | return false 44 | } 45 | } 46 | 47 | /// 邮箱匹配 48 | let mail: String = "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$" 49 | 50 | /// 匹配用户名 字面或者数字组合 4到16位 51 | let Username: String = "^[a-z0-9_-]{4,16}$" 52 | 53 | /// 匹配密码 字面加下划线,6到18位 54 | let Password: String = "^[a-z0-9_-]{6,18}$" 55 | 56 | /// 匹配16进制 57 | let HexValue: String = "^#?([a-f0-9]{6}|[a-f0-9]{3})$" 58 | 59 | ///内容带分割符号 “Anne-Blair” 60 | let Slug: String = "^[a-z0-9-]+$" 61 | 62 | /// 匹配URL 63 | let isURL: String = "^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$" 64 | 65 | /// 匹配IP地址 66 | let IPAddress: String = "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$" 67 | 68 | /// 是HTML
内容<\center> 符合 69 | let HTMLTag: String = "^<([a-z]+)([^<]+)*(?:>(.*)<\\/\\1>|\\s+\\/>)$" 70 | 71 | /// 日期(年-月-日) 72 | let isDate1: String = "(\\d{4}|\\d{2})-((1[0-2])|(0?[1-9]))-(([12][0-9])|(3[01])|(0?[1-9]))" 73 | 74 | /// 日期(月/日/年) 75 | let isDate2: String = "((1[0-2])|(0?[1-9]))/(([12][0-9])|(3[01])|(0?[1-9]))/(\\d{4}|\\d{2})" 76 | 77 | /// 时间(小时:分钟, 24小时制) 78 | let TimeFormat: String = "((1|0?)[0-9]|2[0-3]):([0-5][0-9])" 79 | 80 | /// 是汉字 81 | let isChinese: String = "[\\u4e00-\\u9fa5]" 82 | 83 | /// 中文及全角标点符号(字符) 84 | let ChineseParagraph: String = "[\\u3000-\\u301e\\ufe10-\\ufe19\\ufe30-\\ufe44\\ufe50-\\ufe6b\\uff01-\\uffee]" 85 | 86 | /// 中国大陆固定电话号码 87 | let fixedLineTelephone: String = "(\\d{4}-|\\d{3}-)?(\\d{8}|\\d{7})" 88 | 89 | /// 中国大陆身份证号(15位或18位) 90 | let IdNum: String = "\\d{15}(\\d\\d[0-9xX])?" 91 | 92 | /// 手机号 93 | let isIphoneNum: String = "1\\d{10}" 94 | 95 | /// 邮政编码 96 | let zipCode: String = "[1-9]\\d{5}" 97 | 98 | /// 大于0的整数 99 | let integer = "[1-9]\\d" 100 | 101 | /// 字母 102 | let letter = "^[A-Z]+$" 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /YYGRegular/YYGText.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YYGText.swift 3 | // 24demo 4 | // 5 | // Created by 区块国际-yin on 17/2/10. 6 | // Copyright © 2017年 区块国际-yin. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// Seting AttributedString 12 | /// 13 | /// - Parameters: 14 | /// - color: 颜色 Arry [[RGB,RGB,RGB],[RGB,RGB,RGB]] 15 | /// - content: 内容 Arry ["第一个","第二个"] 16 | /// - size: 字体 Arry [size1,size2] 17 | /// - Returns: 富文本 18 | public func setAttribute(color: [[Int]],content:[String],size: [CGFloat])-> NSMutableAttributedString { 19 | 20 | let str = NSMutableAttributedString() 21 | for i in 0.. String { 32 | let numFormat = NumberFormatter() 33 | numFormat.numberStyle = NumberFormatter.Style.decimal 34 | let num = NSNumber.init(value: f_loat) 35 | return numFormat.string(from: num)! 36 | } 37 | 38 | // MARK: - 数字转换成字符串金额 11121.01 -> "11,121.01" 三位一个逗号 39 | extension NSNumber { 40 | var dollars: String { 41 | let formatter: NumberFormatter = NumberFormatter() 42 | var result: String? 43 | formatter.numberStyle = NumberFormatter.Style.decimal 44 | result = formatter.string(from: self) 45 | if result == nil { 46 | return "error" 47 | } 48 | return result! 49 | } 50 | } 51 | 52 | extension String { 53 | /// 截取第一个到第任意位置 54 | /// 55 | /// - Parameter end: 结束的位值 56 | /// - Returns: 截取后的字符串 57 | func stringCut(end: Int) ->String{ 58 | printLogDebug(self.characters.count) 59 | if !(end < characters.count) { return "截取超出范围" } 60 | let sInde = index(startIndex, offsetBy: end) 61 | return substring(to: sInde) 62 | } 63 | 64 | /// 截取人任意位置到结束 65 | /// 66 | /// - Parameter end: 67 | /// - Returns: 截取后的字符串 68 | func stringCutToEnd(star: Int) -> String { 69 | if !(star < characters.count) { return "截取超出范围" } 70 | let sRang = index(startIndex, offsetBy: star).. String { 81 | if !(locat < characters.count) { return "截取超出范围" } 82 | let str1 = stringCut(end: locat) 83 | let str2 = stringCutToEnd(star: locat) 84 | return str1 + content + str2 85 | } 86 | 87 | /// 计算字符串宽高 88 | /// 89 | /// - Parameter size: size 90 | /// - Returns: CGSize 91 | func getStringSzie(size: CGFloat = 10) -> CGSize { 92 | let baseFont = UIFont.systemFont(ofSize: size) 93 | let size = self.size(attributes: [NSFontAttributeName: baseFont]) 94 | let width = ceil(size.width) + 5 95 | let height = ceil(size.height) 96 | return CGSize(width: width, height: height) 97 | } 98 | 99 | /// 输入字符串 输出数组 100 | /// e.g "qwert" -> ["q","w","e","r","t"] 101 | /// - Returns: ["q","w","e","r","t"] 102 | func stringToArr() -> [String] { 103 | let num = characters.count 104 | if !(num > 0) { return [""] } 105 | var arr: [String] = [] 106 | for i in 0.. "cdef" 115 | /// - Parameters: 116 | /// - start: 开始位置 3 117 | /// - end: 结束位置 6 118 | /// - Returns: 截取后的字符串 "cdef" 119 | func startToEnd(start: Int,end: Int) -> String { 120 | if !(end < characters.count) || start > end { return "取值范围错误" } 121 | var tempStr: String = "" 122 | for i in start...end { 123 | let temp: String = self[self.index(self.startIndex, offsetBy: i - 1)].description 124 | tempStr += temp 125 | } 126 | return tempStr 127 | } 128 | 129 | /// 字符URL格式化 130 | /// 131 | /// - Returns: 格式化的 url 132 | func stringEncoding() -> String { 133 | let url = self.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) 134 | return url! 135 | } 136 | } 137 | 138 | 139 | -------------------------------------------------------------------------------- /YYGRegular/YYGcategory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YYGcategory.swift 3 | // Ecshop 4 | // 5 | // Created by 区块国际-yin on 16/10/24. 6 | // Copyright © 2016年 区块国际-yin. All rights reserved. 7 | // 8 | 9 | 10 | import Foundation 11 | import UIKit 12 | 13 | public func printLogDebug(_ message: T, 14 | file: String = #file, 15 | method: String = #function, 16 | line: Int = #line 17 | ) 18 | { 19 | #if DEBUG 20 | print("------------------\(line) lineBegin-------------------------\n类名称: \((file as NSString).lastPathComponent)\n方法名: \(method)\n信息: \(message)\n------------------\(line) line End-------------------------") 21 | #endif 22 | } 23 | 24 | /// 线程加锁 25 | /// 26 | /// - Parameters: 27 | /// - lock: 加锁对象 28 | /// - dispose: 执行闭包函数, 29 | func synchronized(_ lock: AnyObject,dispose: ()->()) { 30 | objc_sync_enter(lock) 31 | dispose() 32 | objc_sync_exit(lock) 33 | } 34 | 35 | public let UIScreeWidth: CGFloat = UIScreen.main.bounds.size.width 36 | public let UIScreeHeight: CGFloat = UIScreen.main.bounds.size.height 37 | 38 | public let NOW_WIDTH: CGFloat = (UIScreeWidth / 375.0) 39 | public let NOW_HEIGHT: CGFloat = (UIScreeHeight / 667.0) 40 | 41 | extension UIView { 42 | 43 | var x: CGFloat { 44 | get { 45 | return frame.origin.x 46 | } 47 | set { 48 | frame = CGRect(x: newValue, y: frame.origin.y, width: frame.width, height: frame.height) 49 | } 50 | } 51 | 52 | var y: CGFloat { 53 | get { 54 | return frame.origin.y 55 | } 56 | set { 57 | frame = CGRect(x: frame.origin.x, y: newValue, width: frame.width, height: frame.height) 58 | } 59 | } 60 | 61 | var wide: CGFloat { 62 | get { 63 | return frame.size.width 64 | } 65 | set { 66 | frame = CGRect(x: frame.origin.x, y: newValue, width: frame.origin.x + newValue, height: frame.height) 67 | } 68 | } 69 | 70 | var height: CGFloat { 71 | get { 72 | return frame.size.height 73 | } 74 | set { 75 | frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.width, height: frame.origin.y + newValue) 76 | } 77 | } 78 | 79 | var origin: CGPoint { 80 | get { 81 | return frame.origin 82 | } 83 | set { 84 | frame.origin = newValue 85 | } 86 | } 87 | 88 | var size: CGSize { 89 | get { 90 | return frame.size 91 | } 92 | set { 93 | frame.size = newValue 94 | } 95 | } 96 | 97 | var right: CGFloat { 98 | get { 99 | return frame.maxX 100 | } 101 | set { 102 | frame = CGRect(x: newValue-frame.width, y: frame.minY, width: frame.width, height: frame.height) 103 | } 104 | } 105 | 106 | var bottom: CGFloat { 107 | get { 108 | return frame.maxY 109 | } 110 | set { 111 | frame = CGRect(x: frame.minX, y: newValue-frame.height, width: frame.width, height: frame.height) 112 | } 113 | } 114 | } 115 | 116 | //MARK: Convenience methods for UIColor _________________________________________________________________________________________________ 117 | 118 | public extension UIColor { 119 | 120 | /// Init color without divide 255.0 121 | /// 122 | /// - Parameters: 123 | /// - r: (0 ~ 255) red 124 | /// - g: (0 ~ 255) green 125 | /// - b: (0 ~ 255) blue 126 | /// - a: (0 ~ 1) alpha 127 | convenience init(r: Int, g: Int, b: Int, a: CGFloat) { 128 | self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: a) 129 | } 130 | 131 | /// Init color without divide 255.0 132 | /// 133 | /// - Parameters: 134 | /// - r: (0 ~ 255) red 135 | /// - g: (0 ~ 255) green 136 | /// - b: (0 ~ 1) alpha 137 | convenience init(r: Int, g: Int, b: Int) { 138 | self.init(r: r, g: g, b: b, a: 1) 139 | } 140 | 141 | /// Init color with hex code 142 | /// 143 | /// - Parameter hex: hex code (eg. 0x00eeee) 144 | convenience init(hex: Int) { 145 | self.init(r: (hex & 0xff0000) >> 16, g: (hex & 0xff00) >> 8, b: (hex & 0xff), a: 1) 146 | } 147 | 148 | } 149 | 150 | //MARK: 延时使用 ____________________________________________________________________________________________________ 151 | 152 | typealias TaskBlock = (_ cancel : Bool) -> Void 153 | 154 | func delay(_ time: TimeInterval, task: @escaping ()->()) -> TaskBlock? { 155 | 156 | func dispatch_later(block: @escaping ()->()) { 157 | let t = DispatchTime.now() + time 158 | DispatchQueue.main.asyncAfter(deadline: t, execute: block) 159 | } 160 | 161 | var closure: (()->Void)? = task 162 | var result: TaskBlock? 163 | 164 | let delayedClosure: TaskBlock = { 165 | cancel in 166 | if let internalClosure = closure { 167 | if (cancel == false) { 168 | DispatchQueue.main.async(execute: internalClosure) 169 | } 170 | } 171 | closure = nil 172 | result = nil 173 | } 174 | 175 | result = delayedClosure 176 | 177 | dispatch_later { 178 | if let delayedClosure = result { 179 | delayedClosure(false) 180 | } 181 | } 182 | return result 183 | } 184 | 185 | func cancel(_ task: TaskBlock?) { 186 | task?(true) 187 | } 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /YYGRegular/arrayDataSource.swift: -------------------------------------------------------------------------------- 1 | // 2 | // arrayDataSource.swift 3 | // POC 4 | // 5 | // Created by 区块国际-yin on 2017/3/9. 6 | // Copyright © 2017年 blog.aiyinyu.com. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | typealias cellConfigureClasure = (_ cell: Any,_ item: Any,_ indexPath: IndexPath)->Void 12 | 13 | class arrayDataSource: NSObject,UITableViewDataSource { 14 | 15 | private var items: [Any]? 16 | private var cellIdentifier: String? 17 | private var configureCellClasure: cellConfigureClasure 18 | 19 | init(anItems: [Any],identifier: String,clasure: @escaping cellConfigureClasure) { 20 | items = anItems 21 | cellIdentifier = identifier 22 | configureCellClasure = clasure 23 | } 24 | 25 | //MARK: dataSource ________________________________________________________________________________________________ 26 | 27 | func itemAtIndexPath(indexpath: IndexPath) -> Any { 28 | return items![indexpath.row] 29 | } 30 | 31 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 32 | return (items?.count)! 33 | } 34 | 35 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 36 | let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier!, for: indexPath) 37 | let item = itemAtIndexPath(indexpath: indexPath) 38 | configureCellClasure(cell,item,indexPath) 39 | return cell 40 | } 41 | 42 | func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { 43 | return true 44 | } 45 | } 46 | --------------------------------------------------------------------------------