├── .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 | [](https://travis-ci.org/SwiftyJSON/SwiftyJSON) [](https://github.com/Carthage/Carthage)  
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 |
--------------------------------------------------------------------------------