├── SwiftNetDemo ├── MyPlayground.playground │ ├── timeline.xctimeline │ ├── contents.xcplayground │ └── Contents.swift ├── SwiftNetDemo.xcodeproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── SwiftNetDemo.xcscmblueprint └── SwiftNetDemo │ ├── SwiftNetConfigImp.swift │ ├── User.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard │ ├── Info.plist │ ├── AppDelegate.swift │ └── ViewController.swift ├── SwiftNet ├── SwiftNet.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── project.pbxproj └── SwiftNet │ ├── SwiftNet.h │ ├── SwiftNetConfig.swift │ ├── Info.plist │ ├── ModelType.swift │ └── Request.swift ├── SwiftNet.podspec ├── LICENSE └── README.md /SwiftNetDemo/MyPlayground.playground/timeline.xctimeline: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /SwiftNetDemo/MyPlayground.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /SwiftNet/SwiftNet.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftNetDemo/SwiftNetDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftNetDemo/MyPlayground.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: Playground - noun: a place where people can play 2 | 3 | import UIKit 4 | import RxSwift 5 | 6 | 7 | 8 | 9 | func mmmm(m:Bool)->Observable{ 10 | let a = Observable.just(m) 11 | 12 | return a.concat(Observable.never()).throttle(1, scheduler: MainScheduler.instance).take(1) 13 | } 14 | 15 | mmmm(false).subscribeNext { (aa) -> Void in 16 | print(aa) 17 | } -------------------------------------------------------------------------------- /SwiftNet.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'SwiftNet' 3 | s.version = '1.0.0' 4 | s.license = 'MIT' 5 | s.summary = '项目可直接使用的网络请求库' 6 | s.author = { "邓锋" => "704292743@qq.com" } 7 | s.homepage = 'https://github.com/FengDeng/SwiftNet' 8 | s.source = { :git => 'https://github.com/FengDeng/SwiftNet.git', :tag => s.version } 9 | 10 | s.ios.deployment_target = '8.0' 11 | 12 | s.source_files = 'SwiftNet/SwiftNet/*.swift' 13 | 14 | s.dependency 'Alamofire', '~> 3.1.3' 15 | s.dependency 'RxSwift', '~> 2.2.0' 16 | 17 | end 18 | -------------------------------------------------------------------------------- /SwiftNet/SwiftNet/SwiftNet.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftNet.h 3 | // SwiftNet 4 | // 5 | // Created by 邓锋 on 16/2/29. 6 | // Copyright © 2016年 fengdeng. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SwiftNet. 12 | FOUNDATION_EXPORT double SwiftNetVersionNumber; 13 | 14 | //! Project version string for SwiftNet. 15 | FOUNDATION_EXPORT const unsigned char SwiftNetVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /SwiftNet/SwiftNet/SwiftNetConfig.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AKNetworkConfig.swift 3 | // IaskuNetwork 4 | // 5 | // Created by 邓锋 on 16/3/4. 6 | // Copyright © 2016年 iasku. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import RxSwift 11 | import Alamofire 12 | 13 | /** 14 | * 离散型的API设计 必须符合此协议 15 | */ 16 | public protocol SwiftNetConfig{ 17 | var method : Alamofire.Method {get} 18 | var url : URLStringConvertible {get} 19 | var parameters : [String: AnyObject]? {get} 20 | var encoding: ParameterEncoding {get} 21 | var headers: [String: String]? {get} 22 | } 23 | 24 | -------------------------------------------------------------------------------- /SwiftNetDemo/SwiftNetDemo/SwiftNetConfigImp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftNetConfigImp.swift 3 | // SwiftNetDemo 4 | // 5 | // Created by 邓锋 on 16/3/8. 6 | // Copyright © 2016年 fengdeng. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Alamofire 11 | 12 | class SwiftNetConfigImp : SwiftNetConfig { 13 | var method : Alamofire.Method {return .GET} 14 | var url : URLStringConvertible {return "https://api.github.com/users/FengDeng"} 15 | var parameters : [String: AnyObject]? {return nil} 16 | var encoding: ParameterEncoding {return .URL} 17 | var headers: [String: String]? {return nil} 18 | 19 | } -------------------------------------------------------------------------------- /SwiftNetDemo/SwiftNetDemo/User.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // SwiftNetDemo 4 | // 5 | // Created by 邓锋 on 16/3/8. 6 | // Copyright © 2016年 fengdeng. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class User : ModelJSONType{ 12 | 13 | var username = "" 14 | var avatar_url = "" 15 | 16 | required init(){} 17 | 18 | static func from(json: AnyObject?) throws -> Self { 19 | guard let json = json as? [String:AnyObject] else{ 20 | throw NSError(domain: "json 解析出错", code: -1, userInfo: nil) 21 | } 22 | let user = User() 23 | user.avatar_url = (json["avatar_url"] as? String) ?? "" 24 | return autocast(user) 25 | } 26 | } -------------------------------------------------------------------------------- /SwiftNet/SwiftNet/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 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SwiftNet/SwiftNet/ModelType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ModelType.swift 3 | // SwiftNetDemo 4 | // 5 | // Created by 邓锋 on 16/3/7. 6 | // Copyright © 2016年 fengdeng. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | //返回Self 12 | func autocast(x: Any) -> T { 13 | return x as! T 14 | } 15 | 16 | public protocol ModelJSONType{ 17 | //从JSON转化 18 | static func from(json:AnyObject?) throws -> Self 19 | } 20 | 21 | public protocol ModelStringType{ 22 | //从String转化 23 | static func from(string:String?) throws ->Self 24 | } 25 | 26 | public protocol ModelDataType{ 27 | //从Data转化 28 | static func from(data:NSData?) throws ->Self 29 | } 30 | 31 | public protocol ModelDefaultType{ 32 | //默认 33 | static func from(request:NSURLRequest?, response:NSHTTPURLResponse?, data:NSData?) throws ->Self 34 | } 35 | 36 | public protocol ModelPropertyListType{ 37 | //PropertyList 38 | static func from(propertyList:AnyObject?) throws ->Self 39 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 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 | -------------------------------------------------------------------------------- /SwiftNetDemo/SwiftNetDemo/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 | } -------------------------------------------------------------------------------- /SwiftNetDemo/SwiftNetDemo/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 | -------------------------------------------------------------------------------- /SwiftNetDemo/SwiftNetDemo/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 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /SwiftNetDemo/SwiftNetDemo/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 | -------------------------------------------------------------------------------- /SwiftNetDemo/SwiftNetDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SwiftNetDemo 4 | // 5 | // Created by 邓锋 on 16/2/29. 6 | // Copyright © 2016年 fengdeng. 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: [NSObject: AnyObject]?) -> 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 throttle down OpenGL ES frame rates. 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 inactive 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 | -------------------------------------------------------------------------------- /SwiftNetDemo/SwiftNetDemo.xcodeproj/project.xcworkspace/xcshareddata/SwiftNetDemo.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "20F12BDBF84AB08C1ACF3E32B3984E72F44E5EC2", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | 5 | }, 6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 7 | "8B123162C394A0A0A138779108E4C59DD771865A" : 0, 8 | "20F12BDBF84AB08C1ACF3E32B3984E72F44E5EC2" : 0, 9 | "67620B5EFA902936DF04070AF595B76AB0333747" : 0 10 | }, 11 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "A66EC68B-249C-479E-803E-94D7E4A1297F", 12 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 13 | "8B123162C394A0A0A138779108E4C59DD771865A" : "SwiftNet\/RxSwift\/", 14 | "20F12BDBF84AB08C1ACF3E32B3984E72F44E5EC2" : "SwiftNet\/", 15 | "67620B5EFA902936DF04070AF595B76AB0333747" : "SwiftNet\/Alamofire\/" 16 | }, 17 | "DVTSourceControlWorkspaceBlueprintNameKey" : "SwiftNetDemo", 18 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 19 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "SwiftNetDemo\/SwiftNetDemo.xcodeproj", 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 21 | { 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "git.oschina.net:fengdeng\/SwiftNet.git", 23 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 24 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "20F12BDBF84AB08C1ACF3E32B3984E72F44E5EC2" 25 | }, 26 | { 27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/Alamofire\/Alamofire.git", 28 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 29 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "67620B5EFA902936DF04070AF595B76AB0333747" 30 | }, 31 | { 32 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/ReactiveX\/RxSwift.git", 33 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 34 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "8B123162C394A0A0A138779108E4C59DD771865A" 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /SwiftNetDemo/SwiftNetDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SwiftNetDemo 4 | // 5 | // Created by 邓锋 on 16/2/29. 6 | // Copyright © 2016年 fengdeng. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftNet 11 | import Alamofire 12 | import RxSwift 13 | 14 | class ViewController: UIViewController { 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | // Do any additional setup after loading the view, typically from a nib. 19 | 20 | // Request(url: "https://api.github.com/users/FengDeng") 21 | // .beforeValidate({print("验证前先配置一些东西哈")}) 22 | // .validate({throw NSError(domain: "validate error", code: -1, userInfo: nil)}) 23 | // .beforeRequest({print("我要请求啦")}) 24 | // .responseJSON(User) 25 | // .subscribeNext { (user) -> Void in 26 | // print(user.avatar_url) 27 | // } 28 | // 29 | // Request(url: "https://api.github.com/users/FengDeng").responseJSON(User).subscribeNext { (user) -> Void in 30 | // print(user.avatar_url) 31 | // } 32 | // 33 | // Request(config: SwiftNetConfigImp()).responseJSON(User).subscribeNext { (user) -> Void in 34 | // print(user.avatar_url) 35 | // } 36 | 37 | Observable.combineLatest(Request(url: "https://api.github.com/users/FengDeng").responseJSON(User), Request(url: "https://api.github.com/users/tangqiaoboy").responseJSON(User)) { (user1, user2) -> User in 38 | let user = User() 39 | user.avatar_url = user1.avatar_url + user2.avatar_url 40 | return user 41 | }.subscribe { (event) -> Void in 42 | switch event{ 43 | case .Completed: 44 | print("com") 45 | case .Next(let user): 46 | print(user.avatar_url) 47 | case .Error(let error): 48 | print(error) 49 | } 50 | } 51 | 52 | 53 | } 54 | 55 | override func didReceiveMemoryWarning() { 56 | super.didReceiveMemoryWarning() 57 | // Dispose of any resources that can be recreated. 58 | } 59 | 60 | 61 | } 62 | 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftNet 2 | 直接可用的Swift 网络库。 3 | 4 | 5 | ###没想到还有人用的。这个不维护了。新建链接可以看看 6 | [CNNetwork](https://github.com/FengDeng/CNNetwork) 7 | 8 | 9 | ##Request 10 | 11 | 采用链式调用配置Request 12 | 13 | Request(url: "https://api.github.com/users/FengDeng").method(.GET).parameters(["":""]).headers(["":""])…… 14 | 15 | 请求前参数验证 16 | 17 | Request(url: "https://api.github.com/users/FengDeng") 18 | .beforeValidate({print("验证前先配置一些东西哈")}) 19 | .validate({throw NSError(domain: "validate error", code: -1, userInfo: nil)}) 20 | .beforeRequest({print("我要请求啦")}) 21 | .responseJSON(User) 22 | .subscribeNext { (user) -> Void in 23 | print(user.avatar_url) 24 | } 25 | 26 | 27 | 所有的闭包都可以直接抛出异常,一直走到Response的error里处理 28 | 29 | ##为什么返回Observable。 30 | ####处理多请求同时返回 31 | 32 | Observable.combineLatest(Request(url: "https://api.github.com/users/FengDeng").responseJSON(User), Request(url: "https://api.github.com/users/tangqiaoboy").responseJSON(User)) { (user1, user2) -> User in 33 | let user = User() 34 | user.avatar_url = user1.avatar_url + user2.avatar_url 35 | return user 36 | }.subscribe { (event) -> Void in 37 | switch event{ 38 | case .Completed: 39 | print("com") 40 | case .Next(let user): 41 | print(user.avatar_url) 42 | case .Error(let error): 43 | print(error) 44 | } 45 | } 46 | 47 | 这里就是两个用户都获取到才会调用下面的方法。这是RxSwift里的特性了。因为这里返回了Observable对象,所以很多特性都可以使用 48 | 49 | 等等 50 | 51 | ##可用于两种API设计 52 | 53 | 54 | 1. 集约型API设计 55 | 56 | Request(url: "https://api.github.com/users/FengDeng").responseJSON().subscribeNext { (json) -> Void in 57 | if let json = json{ 58 | print(json) 59 | } 60 | } 61 | 62 | 2. 离散型API设计 63 | 64 | 首先创建一个符合 SwiftNetConfig 协议的类或结构体 65 | 66 | 使用此类的实例来初始化Request 67 | 68 | //离散型的文件 69 | class SwiftNetConfigImp : SwiftNetConfig { 70 | var method : Alamofire.Method {return .GET} 71 | var url : URLStringConvertible {return "https://api.github.com/users/FengDeng"} 72 | var parameters : [String: AnyObject]? {return nil} 73 | var encoding: ParameterEncoding {return .URL} 74 | var headers: [String: String]? {return nil} 75 | 76 | } 77 | 78 | //请求 79 | Request(config: SwiftNetConfigImp()).responseJSON(User).subscribeNext { (user) -> Void in 80 | print(user.avatar_url) 81 | } 82 | 83 | 84 | 85 | 86 | ##Response 87 | 88 | 返回值参考Alamofire设计 也调用Alamofire的接口。 89 | 90 | 返回JSON,Data,String等等,全部包装成Observable类以供订阅 91 | 92 | 也可以在返回的同时进行Model化。参考项目中的demo。至于您选择YYModel,MJExtension,SwiftJSON,Argo等等都可以 93 | 94 | ###Model转化 95 | 96 | responseJSON(User)->Observable 97 | 98 | 等等 99 | 100 | 此处的User类需要实现ModelJSONType协议 101 | 102 | ###不使用Model转化 103 | 104 | responseJSON()->Observable 105 | 106 | 107 | ##Cocoapods 108 | 109 | pod 'SwiftNet', git: 'https://github.com/FengDeng/SwiftNet.git' 110 | 111 | ##使用的第三方库 112 | 113 | [RxSwift](https://github.com/ReactiveX/RxSwift) 114 | 115 | [Alamofire](https://github.com/Alamofire/Alamofire) 116 | 117 | 感谢RxSwift 和 Alamofire 118 | -------------------------------------------------------------------------------- /SwiftNet/SwiftNet.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9F700B4C1C83D1E7005BB302 /* SwiftNet.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F700B4B1C83D1E7005BB302 /* SwiftNet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 9F700F201C83D649005BB302 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F700F1C1C83D649005BB302 /* Alamofire.framework */; }; 12 | 9F700F211C83D649005BB302 /* RxBlocking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F700F1D1C83D649005BB302 /* RxBlocking.framework */; }; 13 | 9F700F221C83D649005BB302 /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F700F1E1C83D649005BB302 /* RxCocoa.framework */; }; 14 | 9F700F231C83D649005BB302 /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F700F1F1C83D649005BB302 /* RxSwift.framework */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXFileReference section */ 18 | 9F700B481C83D1E7005BB302 /* SwiftNet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftNet.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 19 | 9F700B4B1C83D1E7005BB302 /* SwiftNet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftNet.h; sourceTree = ""; }; 20 | 9F700B4D1C83D1E7005BB302 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 21 | 9F700F1C1C83D649005BB302 /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = "../Alamofire/build/Debug-iphoneos/Alamofire.framework"; sourceTree = ""; }; 22 | 9F700F1D1C83D649005BB302 /* RxBlocking.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxBlocking.framework; path = "../RxSwift/build/Debug-iphoneos/RxBlocking.framework"; sourceTree = ""; }; 23 | 9F700F1E1C83D649005BB302 /* RxCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxCocoa.framework; path = "../RxSwift/build/Debug-iphoneos/RxCocoa.framework"; sourceTree = ""; }; 24 | 9F700F1F1C83D649005BB302 /* RxSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxSwift.framework; path = "../RxSwift/build/Debug-iphoneos/RxSwift.framework"; sourceTree = ""; }; 25 | /* End PBXFileReference section */ 26 | 27 | /* Begin PBXFrameworksBuildPhase section */ 28 | 9F700B441C83D1E7005BB302 /* Frameworks */ = { 29 | isa = PBXFrameworksBuildPhase; 30 | buildActionMask = 2147483647; 31 | files = ( 32 | 9F700F201C83D649005BB302 /* Alamofire.framework in Frameworks */, 33 | 9F700F211C83D649005BB302 /* RxBlocking.framework in Frameworks */, 34 | 9F700F221C83D649005BB302 /* RxCocoa.framework in Frameworks */, 35 | 9F700F231C83D649005BB302 /* RxSwift.framework in Frameworks */, 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | 9F700B3E1C83D1E7005BB302 = { 43 | isa = PBXGroup; 44 | children = ( 45 | 9F700F1C1C83D649005BB302 /* Alamofire.framework */, 46 | 9F700F1D1C83D649005BB302 /* RxBlocking.framework */, 47 | 9F700F1E1C83D649005BB302 /* RxCocoa.framework */, 48 | 9F700F1F1C83D649005BB302 /* RxSwift.framework */, 49 | 9F700B4A1C83D1E7005BB302 /* SwiftNet */, 50 | 9F700B491C83D1E7005BB302 /* Products */, 51 | ); 52 | sourceTree = ""; 53 | }; 54 | 9F700B491C83D1E7005BB302 /* Products */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | 9F700B481C83D1E7005BB302 /* SwiftNet.framework */, 58 | ); 59 | name = Products; 60 | sourceTree = ""; 61 | }; 62 | 9F700B4A1C83D1E7005BB302 /* SwiftNet */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | 9F700B4B1C83D1E7005BB302 /* SwiftNet.h */, 66 | 9F700B4D1C83D1E7005BB302 /* Info.plist */, 67 | ); 68 | path = SwiftNet; 69 | sourceTree = ""; 70 | }; 71 | /* End PBXGroup section */ 72 | 73 | /* Begin PBXHeadersBuildPhase section */ 74 | 9F700B451C83D1E7005BB302 /* Headers */ = { 75 | isa = PBXHeadersBuildPhase; 76 | buildActionMask = 2147483647; 77 | files = ( 78 | 9F700B4C1C83D1E7005BB302 /* SwiftNet.h in Headers */, 79 | ); 80 | runOnlyForDeploymentPostprocessing = 0; 81 | }; 82 | /* End PBXHeadersBuildPhase section */ 83 | 84 | /* Begin PBXNativeTarget section */ 85 | 9F700B471C83D1E7005BB302 /* SwiftNet */ = { 86 | isa = PBXNativeTarget; 87 | buildConfigurationList = 9F700B501C83D1E7005BB302 /* Build configuration list for PBXNativeTarget "SwiftNet" */; 88 | buildPhases = ( 89 | 9F700B431C83D1E7005BB302 /* Sources */, 90 | 9F700B441C83D1E7005BB302 /* Frameworks */, 91 | 9F700B451C83D1E7005BB302 /* Headers */, 92 | 9F700B461C83D1E7005BB302 /* Resources */, 93 | ); 94 | buildRules = ( 95 | ); 96 | dependencies = ( 97 | ); 98 | name = SwiftNet; 99 | productName = SwiftNet; 100 | productReference = 9F700B481C83D1E7005BB302 /* SwiftNet.framework */; 101 | productType = "com.apple.product-type.framework"; 102 | }; 103 | /* End PBXNativeTarget section */ 104 | 105 | /* Begin PBXProject section */ 106 | 9F700B3F1C83D1E7005BB302 /* Project object */ = { 107 | isa = PBXProject; 108 | attributes = { 109 | LastUpgradeCheck = 0720; 110 | ORGANIZATIONNAME = fengdeng; 111 | TargetAttributes = { 112 | 9F700B471C83D1E7005BB302 = { 113 | CreatedOnToolsVersion = 7.2; 114 | }; 115 | }; 116 | }; 117 | buildConfigurationList = 9F700B421C83D1E7005BB302 /* Build configuration list for PBXProject "SwiftNet" */; 118 | compatibilityVersion = "Xcode 3.2"; 119 | developmentRegion = English; 120 | hasScannedForEncodings = 0; 121 | knownRegions = ( 122 | en, 123 | ); 124 | mainGroup = 9F700B3E1C83D1E7005BB302; 125 | productRefGroup = 9F700B491C83D1E7005BB302 /* Products */; 126 | projectDirPath = ""; 127 | projectRoot = ""; 128 | targets = ( 129 | 9F700B471C83D1E7005BB302 /* SwiftNet */, 130 | ); 131 | }; 132 | /* End PBXProject section */ 133 | 134 | /* Begin PBXResourcesBuildPhase section */ 135 | 9F700B461C83D1E7005BB302 /* Resources */ = { 136 | isa = PBXResourcesBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | ); 140 | runOnlyForDeploymentPostprocessing = 0; 141 | }; 142 | /* End PBXResourcesBuildPhase section */ 143 | 144 | /* Begin PBXSourcesBuildPhase section */ 145 | 9F700B431C83D1E7005BB302 /* Sources */ = { 146 | isa = PBXSourcesBuildPhase; 147 | buildActionMask = 2147483647; 148 | files = ( 149 | ); 150 | runOnlyForDeploymentPostprocessing = 0; 151 | }; 152 | /* End PBXSourcesBuildPhase section */ 153 | 154 | /* Begin XCBuildConfiguration section */ 155 | 9F700B4E1C83D1E7005BB302 /* Debug */ = { 156 | isa = XCBuildConfiguration; 157 | buildSettings = { 158 | ALWAYS_SEARCH_USER_PATHS = NO; 159 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 160 | CLANG_CXX_LIBRARY = "libc++"; 161 | CLANG_ENABLE_MODULES = YES; 162 | CLANG_ENABLE_OBJC_ARC = YES; 163 | CLANG_WARN_BOOL_CONVERSION = YES; 164 | CLANG_WARN_CONSTANT_CONVERSION = YES; 165 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 166 | CLANG_WARN_EMPTY_BODY = YES; 167 | CLANG_WARN_ENUM_CONVERSION = YES; 168 | CLANG_WARN_INT_CONVERSION = YES; 169 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 170 | CLANG_WARN_UNREACHABLE_CODE = YES; 171 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 172 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 173 | COPY_PHASE_STRIP = NO; 174 | CURRENT_PROJECT_VERSION = 1; 175 | DEBUG_INFORMATION_FORMAT = dwarf; 176 | ENABLE_STRICT_OBJC_MSGSEND = YES; 177 | ENABLE_TESTABILITY = YES; 178 | GCC_C_LANGUAGE_STANDARD = gnu99; 179 | GCC_DYNAMIC_NO_PIC = NO; 180 | GCC_NO_COMMON_BLOCKS = YES; 181 | GCC_OPTIMIZATION_LEVEL = 0; 182 | GCC_PREPROCESSOR_DEFINITIONS = ( 183 | "DEBUG=1", 184 | "$(inherited)", 185 | ); 186 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 187 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 188 | GCC_WARN_UNDECLARED_SELECTOR = YES; 189 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 190 | GCC_WARN_UNUSED_FUNCTION = YES; 191 | GCC_WARN_UNUSED_VARIABLE = YES; 192 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 193 | MTL_ENABLE_DEBUG_INFO = YES; 194 | ONLY_ACTIVE_ARCH = YES; 195 | SDKROOT = iphoneos; 196 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 197 | TARGETED_DEVICE_FAMILY = "1,2"; 198 | VERSIONING_SYSTEM = "apple-generic"; 199 | VERSION_INFO_PREFIX = ""; 200 | }; 201 | name = Debug; 202 | }; 203 | 9F700B4F1C83D1E7005BB302 /* Release */ = { 204 | isa = XCBuildConfiguration; 205 | buildSettings = { 206 | ALWAYS_SEARCH_USER_PATHS = NO; 207 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 208 | CLANG_CXX_LIBRARY = "libc++"; 209 | CLANG_ENABLE_MODULES = YES; 210 | CLANG_ENABLE_OBJC_ARC = YES; 211 | CLANG_WARN_BOOL_CONVERSION = YES; 212 | CLANG_WARN_CONSTANT_CONVERSION = YES; 213 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 214 | CLANG_WARN_EMPTY_BODY = YES; 215 | CLANG_WARN_ENUM_CONVERSION = YES; 216 | CLANG_WARN_INT_CONVERSION = YES; 217 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 218 | CLANG_WARN_UNREACHABLE_CODE = YES; 219 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 220 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 221 | COPY_PHASE_STRIP = NO; 222 | CURRENT_PROJECT_VERSION = 1; 223 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 224 | ENABLE_NS_ASSERTIONS = NO; 225 | ENABLE_STRICT_OBJC_MSGSEND = YES; 226 | GCC_C_LANGUAGE_STANDARD = gnu99; 227 | GCC_NO_COMMON_BLOCKS = YES; 228 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 229 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 230 | GCC_WARN_UNDECLARED_SELECTOR = YES; 231 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 232 | GCC_WARN_UNUSED_FUNCTION = YES; 233 | GCC_WARN_UNUSED_VARIABLE = YES; 234 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 235 | MTL_ENABLE_DEBUG_INFO = NO; 236 | SDKROOT = iphoneos; 237 | TARGETED_DEVICE_FAMILY = "1,2"; 238 | VALIDATE_PRODUCT = YES; 239 | VERSIONING_SYSTEM = "apple-generic"; 240 | VERSION_INFO_PREFIX = ""; 241 | }; 242 | name = Release; 243 | }; 244 | 9F700B511C83D1E7005BB302 /* Debug */ = { 245 | isa = XCBuildConfiguration; 246 | buildSettings = { 247 | DEFINES_MODULE = YES; 248 | DYLIB_COMPATIBILITY_VERSION = 1; 249 | DYLIB_CURRENT_VERSION = 1; 250 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 251 | INFOPLIST_FILE = SwiftNet/Info.plist; 252 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 253 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 254 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 255 | PRODUCT_BUNDLE_IDENTIFIER = com.fengdeng.SwiftNet; 256 | PRODUCT_NAME = "$(TARGET_NAME)"; 257 | SKIP_INSTALL = YES; 258 | }; 259 | name = Debug; 260 | }; 261 | 9F700B521C83D1E7005BB302 /* Release */ = { 262 | isa = XCBuildConfiguration; 263 | buildSettings = { 264 | DEFINES_MODULE = YES; 265 | DYLIB_COMPATIBILITY_VERSION = 1; 266 | DYLIB_CURRENT_VERSION = 1; 267 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 268 | INFOPLIST_FILE = SwiftNet/Info.plist; 269 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 270 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 271 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 272 | PRODUCT_BUNDLE_IDENTIFIER = com.fengdeng.SwiftNet; 273 | PRODUCT_NAME = "$(TARGET_NAME)"; 274 | SKIP_INSTALL = YES; 275 | }; 276 | name = Release; 277 | }; 278 | /* End XCBuildConfiguration section */ 279 | 280 | /* Begin XCConfigurationList section */ 281 | 9F700B421C83D1E7005BB302 /* Build configuration list for PBXProject "SwiftNet" */ = { 282 | isa = XCConfigurationList; 283 | buildConfigurations = ( 284 | 9F700B4E1C83D1E7005BB302 /* Debug */, 285 | 9F700B4F1C83D1E7005BB302 /* Release */, 286 | ); 287 | defaultConfigurationIsVisible = 0; 288 | defaultConfigurationName = Release; 289 | }; 290 | 9F700B501C83D1E7005BB302 /* Build configuration list for PBXNativeTarget "SwiftNet" */ = { 291 | isa = XCConfigurationList; 292 | buildConfigurations = ( 293 | 9F700B511C83D1E7005BB302 /* Debug */, 294 | 9F700B521C83D1E7005BB302 /* Release */, 295 | ); 296 | defaultConfigurationIsVisible = 0; 297 | defaultConfigurationName = Release; 298 | }; 299 | /* End XCConfigurationList section */ 300 | }; 301 | rootObject = 9F700B3F1C83D1E7005BB302 /* Project object */; 302 | } 303 | -------------------------------------------------------------------------------- /SwiftNet/SwiftNet/Request.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Request.swift 3 | // IaskuNetwork 4 | // 5 | // Created by 邓锋 on 16/3/4. 6 | // Copyright © 2016年 iasku. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Alamofire 11 | import RxSwift 12 | 13 | public class Request{ 14 | 15 | //public typealias Success = O->Void 16 | public typealias Failure = ErrorType ->Void 17 | 18 | //generate request 19 | //Method 20 | //public typealias setMethod = Void ->Alamofire.Method 21 | private var method : Alamofire.Method = Alamofire.Method.GET 22 | 23 | //url 24 | //public typealias setURL = Void ->URLStringConvertible 25 | private var url : URLStringConvertible 26 | 27 | //parameters 28 | //public typealias setParameters = Void ->[String: AnyObject]? 29 | private var parameters : [String: AnyObject]? 30 | 31 | //encoding 32 | //public typealias setEncoding = Void ->ParameterEncoding 33 | private var encoding: ParameterEncoding = .URL 34 | 35 | //headers 36 | //public typealias setHeaders = Void ->[String: String]? 37 | private var headers: [String: String]? 38 | 39 | //timeout 40 | //public typealias setTimeoutInterval = Void ->NSTimeInterval 41 | private var timeoutInterval : NSTimeInterval = 20 42 | 43 | private var config = true 44 | 45 | 46 | //request life 47 | //beforeValidate 48 | public typealias setBeforeValidate = Void throws ->() 49 | var beforeValidate : setBefore? 50 | 51 | //validate 52 | public typealias setValidate = Void throws ->() 53 | var validate : setValidate = {} 54 | 55 | //before 56 | public typealias setBefore = Void throws ->() 57 | var beforeRequest : setBefore? 58 | 59 | public init(config:SwiftNetConfig){ 60 | self.url = config.url 61 | self.method = config.method 62 | self.parameters = config.parameters 63 | self.encoding = config.encoding 64 | self.headers = config.headers 65 | } 66 | 67 | public init(url:URLStringConvertible){ 68 | self.url = url 69 | } 70 | 71 | convenience public init(method:Alamofire.Method,url:URLStringConvertible){ 72 | self.init(url:url) 73 | self.method = method 74 | } 75 | 76 | deinit{ 77 | print("Request deinit") 78 | } 79 | 80 | 81 | } 82 | 83 | // MARK: - Request Parameters 84 | extension Request{ 85 | //setting 86 | public func method(method:Alamofire.Method)->Self{ 87 | self.method = method 88 | return self 89 | } 90 | 91 | public func parameters(parameters:[String: AnyObject])->Self{ 92 | self.parameters = parameters 93 | return self 94 | } 95 | 96 | public func encoding(encoding:ParameterEncoding)->Self{ 97 | self.encoding = encoding 98 | return self 99 | } 100 | 101 | public func headers(headers:[String: String])->Self{ 102 | self.headers = headers 103 | return self 104 | } 105 | 106 | public func config(config:Bool)->Self{ 107 | self.config = config 108 | return self 109 | } 110 | 111 | } 112 | 113 | 114 | // MARK: - Life Circle 115 | extension Request{ 116 | //life 117 | public func beforeValidate(beforeValidate:setBefore)->Self{ 118 | self.beforeValidate = beforeValidate 119 | return self 120 | } 121 | 122 | public func validate(validate:setValidate)->Self{ 123 | self.validate = validate 124 | return self 125 | } 126 | 127 | public func beforeRequest(beforeRequest:setBefore)->Self{ 128 | self.beforeRequest = beforeRequest 129 | return self 130 | } 131 | } 132 | 133 | // MARK: - JSON 134 | extension Request{ 135 | public func responseJSON(modelClass:K.Type)->Observable{ 136 | return Observable.create({/*[weak /*weakSelf*/self = self]*/observer -> Disposable in 137 | /*guard let /*weakSelf*/self = /*weakSelf*/self else { 138 | observer.on(.Completed) 139 | return NopDisposable.instance 140 | }*/ 141 | 142 | //validata 143 | do{ 144 | try /*weakSelf*/self.beforeValidate?() 145 | try /*weakSelf*/self.validate() 146 | try /*weakSelf*/self.beforeRequest?() 147 | 148 | }catch{ 149 | observer.onError(error) 150 | } 151 | let re = request(/*weakSelf*/self.method, /*weakSelf*/self.url, parameters: /*weakSelf*/self.parameters, encoding: /*weakSelf*/self.encoding, headers: /*weakSelf*/self.headers) 152 | re.responseJSON(completionHandler: { res -> Void in 153 | if let error = res.result.error { 154 | observer.onError(error) 155 | } 156 | do{ 157 | let k = try K.from(res.result.value) 158 | observer.onNext(k) 159 | observer.onCompleted() 160 | }catch{ 161 | observer.onError(error) 162 | } 163 | }) 164 | return AnonymousDisposable{ 165 | re.cancel() 166 | } 167 | }) 168 | } 169 | 170 | public func responseJSON()->Observable{ 171 | return Observable.create({/*[weak /*weakSelf*/self = self]*/ observer -> Disposable in 172 | /*guard let /*weakSelf*/self = /*weakSelf*/self else { 173 | observer.on(.Completed) 174 | return NopDisposable.instance 175 | }*/ 176 | //validata 177 | do{ 178 | try /*weakSelf*/self.beforeValidate?() 179 | try /*weakSelf*/self.validate() 180 | try /*weakSelf*/self.beforeRequest?() 181 | 182 | }catch{ 183 | observer.onError(error) 184 | } 185 | let re = request(/*weakSelf*/self.method, /*weakSelf*/self.url, parameters: /*weakSelf*/self.parameters, encoding: /*weakSelf*/self.encoding, headers: /*weakSelf*/self.headers) 186 | re.responseJSON(completionHandler: { res -> Void in 187 | if let error = res.result.error { 188 | observer.onError(error) 189 | } 190 | observer.onNext(res.result.value) 191 | observer.onCompleted() 192 | }) 193 | return AnonymousDisposable{ 194 | re.cancel() 195 | } 196 | }) 197 | } 198 | } 199 | 200 | // MARK: - String 201 | extension Request{ 202 | public func responseString(modelClass:K.Type,encoding:NSStringEncoding? = nil)->Observable{ 203 | return Observable.create({ /*[weak /*weakSelf*/self = self]*/ observer -> Disposable in 204 | /*guard let /*weakSelf*/self = /*weakSelf*/self else { 205 | observer.on(.Completed) 206 | return NopDisposable.instance 207 | }*/ 208 | //validata 209 | do{ 210 | try /*weakSelf*/self.beforeValidate?() 211 | try /*weakSelf*/self.validate() 212 | try /*weakSelf*/self.beforeRequest?() 213 | 214 | }catch{ 215 | observer.onError(error) 216 | } 217 | let re = request(/*weakSelf*/self.method, /*weakSelf*/self.url, parameters: /*weakSelf*/self.parameters, encoding: /*weakSelf*/self.encoding, headers: /*weakSelf*/self.headers) 218 | re.responseString(encoding: encoding, completionHandler: { res -> Void in 219 | if let error = res.result.error { 220 | observer.onError(error) 221 | } 222 | do{ 223 | let k = try K.from(res.result.value) 224 | observer.onNext(k) 225 | observer.onCompleted() 226 | }catch{ 227 | observer.onError(error) 228 | } 229 | }) 230 | return AnonymousDisposable{ 231 | re.cancel() 232 | } 233 | }) 234 | } 235 | public func responseString(encoding:NSStringEncoding? = nil)->Observable{ 236 | return Observable.create({/*[weak /*weakSelf*/self = self]*/ observer -> Disposable in 237 | /*guard let /*weakSelf*/self = /*weakSelf*/self else { 238 | observer.on(.Completed) 239 | return NopDisposable.instance 240 | }*/ 241 | //validata 242 | do{ 243 | try /*weakSelf*/self.beforeValidate?() 244 | try /*weakSelf*/self.validate() 245 | try /*weakSelf*/self.beforeRequest?() 246 | 247 | }catch{ 248 | observer.onError(error) 249 | } 250 | let re = request(/*weakSelf*/self.method, /*weakSelf*/self.url, parameters: /*weakSelf*/self.parameters, encoding: /*weakSelf*/self.encoding, headers: /*weakSelf*/self.headers) 251 | re.responseString(encoding: encoding, completionHandler: { res -> Void in 252 | if let error = res.result.error { 253 | observer.onError(error) 254 | } 255 | observer.onNext(res.result.value) 256 | observer.onCompleted() 257 | }) 258 | return AnonymousDisposable{ 259 | re.cancel() 260 | } 261 | }) 262 | } 263 | } 264 | 265 | // MARK: - Data 266 | extension Request{ 267 | public func responseData(modelClass:K.Type)->Observable{ 268 | return Observable.create({/*[weak /*weakSelf*/self = self]*/ observer -> Disposable in 269 | /*guard let /*weakSelf*/self = /*weakSelf*/self else { 270 | observer.on(.Completed) 271 | return NopDisposable.instance 272 | }*/ 273 | //validata 274 | do{ 275 | try /*weakSelf*/self.beforeValidate?() 276 | try /*weakSelf*/self.validate() 277 | try /*weakSelf*/self.beforeRequest?() 278 | 279 | }catch{ 280 | observer.onError(error) 281 | } 282 | let re = request(/*weakSelf*/self.method, /*weakSelf*/self.url, parameters: /*weakSelf*/self.parameters, encoding: /*weakSelf*/self.encoding, headers: /*weakSelf*/self.headers) 283 | re.responseData({ res -> Void in 284 | if let error = res.result.error { 285 | observer.onError(error) 286 | } 287 | do{ 288 | let k = try K.from(res.result.value) 289 | observer.onNext(k) 290 | observer.onCompleted() 291 | }catch{ 292 | observer.onError(error) 293 | } 294 | }) 295 | return AnonymousDisposable{ 296 | re.cancel() 297 | } 298 | }) 299 | } 300 | 301 | public func responseData()->Observable{ 302 | return Observable.create({/*[weak /*weakSelf*/self = self]*/ observer -> Disposable in 303 | /*guard let /*weakSelf*/self = /*weakSelf*/self else { 304 | observer.on(.Completed) 305 | return NopDisposable.instance 306 | }*/ 307 | //validata 308 | do{ 309 | try /*weakSelf*/self.beforeValidate?() 310 | try /*weakSelf*/self.validate() 311 | try /*weakSelf*/self.beforeRequest?() 312 | 313 | }catch{ 314 | observer.onError(error) 315 | } 316 | let re = request(/*weakSelf*/self.method, /*weakSelf*/self.url, parameters: /*weakSelf*/self.parameters, encoding: /*weakSelf*/self.encoding, headers: /*weakSelf*/self.headers) 317 | re.responseData({ res -> Void in 318 | if let error = res.result.error { 319 | observer.onError(error) 320 | } 321 | observer.onNext(res.result.value) 322 | observer.onCompleted() 323 | }) 324 | return AnonymousDisposable{ 325 | re.cancel() 326 | } 327 | }) 328 | } 329 | } 330 | 331 | // MARK: - Default Response 332 | extension Request{ 333 | public func response(modelClass:K.Type)->Observable{ 334 | return Observable.create({/*[weak /*weakSelf*/self = self]*/ observer -> Disposable in 335 | /*guard let /*weakSelf*/self = /*weakSelf*/self else { 336 | observer.on(.Completed) 337 | return NopDisposable.instance 338 | }*/ 339 | //validata 340 | do{ 341 | try /*weakSelf*/self.beforeValidate?() 342 | try /*weakSelf*/self.validate() 343 | try /*weakSelf*/self.beforeRequest?() 344 | 345 | }catch{ 346 | observer.onError(error) 347 | } 348 | let re = request(/*weakSelf*/self.method, /*weakSelf*/self.url, parameters: /*weakSelf*/self.parameters, encoding: /*weakSelf*/self.encoding, headers: /*weakSelf*/self.headers) 349 | re.response(completionHandler: { (re, res, data, error) -> Void in 350 | if let error = error { 351 | observer.onError(error) 352 | } 353 | do{ 354 | let k = try K.from(re, response: res, data: data) 355 | observer.onNext(k) 356 | observer.onCompleted() 357 | }catch{ 358 | observer.onError(error) 359 | } 360 | }) 361 | return AnonymousDisposable{ 362 | re.cancel() 363 | } 364 | }) 365 | } 366 | 367 | public func response()->Observable<(NSURLRequest?, NSHTTPURLResponse?, NSData?)>{ 368 | return Observable.create({/*[weak /*weakSelf*/self = self]*/ observer -> Disposable in 369 | /*guard let /*weakSelf*/self = /*weakSelf*/self else { 370 | observer.on(.Completed) 371 | return NopDisposable.instance 372 | }*/ 373 | //validata 374 | do{ 375 | try /*weakSelf*/self.beforeValidate?() 376 | try /*weakSelf*/self.validate() 377 | try /*weakSelf*/self.beforeRequest?() 378 | 379 | }catch{ 380 | observer.onError(error) 381 | } 382 | let re = request(/*weakSelf*/self.method, /*weakSelf*/self.url, parameters: /*weakSelf*/self.parameters, encoding: /*weakSelf*/self.encoding, headers: /*weakSelf*/self.headers) 383 | re.response(completionHandler: { (re, res, data, error) -> Void in 384 | if let error = error { 385 | observer.onError(error) 386 | } 387 | observer.onNext((re,res,data)) 388 | observer.onCompleted() 389 | }) 390 | return AnonymousDisposable{ 391 | re.cancel() 392 | } 393 | }) 394 | } 395 | } 396 | 397 | // MARK: - PropertyList 398 | extension Request{ 399 | public func responsePropertyList(modelClass:K.Type,options:NSPropertyListReadOptions = NSPropertyListReadOptions())->Observable{ 400 | return Observable.create({/*[weak /*weakSelf*/self = self]*/ observer -> Disposable in 401 | /*guard let /*weakSelf*/self = /*weakSelf*/self else { 402 | observer.on(.Completed) 403 | return NopDisposable.instance 404 | }*/ 405 | //validata 406 | do{ 407 | try /*weakSelf*/self.beforeValidate?() 408 | try /*weakSelf*/self.validate() 409 | try /*weakSelf*/self.beforeRequest?() 410 | 411 | }catch{ 412 | observer.onError(error) 413 | } 414 | let re = request(/*weakSelf*/self.method, /*weakSelf*/self.url, parameters: /*weakSelf*/self.parameters, encoding: /*weakSelf*/self.encoding, headers: /*weakSelf*/self.headers) 415 | re.responsePropertyList(options: options, completionHandler:{ res -> Void in 416 | if let error = res.result.error { 417 | observer.onError(error) 418 | } 419 | do{ 420 | let k = try K.from(res.result.value) 421 | observer.onNext(k) 422 | observer.onCompleted() 423 | }catch{ 424 | observer.onError(error) 425 | } 426 | }) 427 | return AnonymousDisposable{ 428 | re.cancel() 429 | } 430 | }) 431 | } 432 | 433 | public func responsePropertyList(options:NSPropertyListReadOptions = NSPropertyListReadOptions())->Observable{ 434 | return Observable.create({/*[weak /*weakSelf*/self = self]*/ observer -> Disposable in 435 | /*guard let /*weakSelf*/self = /*weakSelf*/self else { 436 | observer.on(.Completed) 437 | return NopDisposable.instance 438 | }*/ 439 | //validata 440 | do{ 441 | try /*weakSelf*/self.beforeValidate?() 442 | try /*weakSelf*/self.validate() 443 | try /*weakSelf*/self.beforeRequest?() 444 | 445 | }catch{ 446 | observer.onError(error) 447 | } 448 | let re = request(/*weakSelf*/self.method, /*weakSelf*/self.url, parameters: /*weakSelf*/self.parameters, encoding: /*weakSelf*/self.encoding, headers: /*weakSelf*/self.headers) 449 | re.responsePropertyList(options: options, completionHandler:{ res -> Void in 450 | if let error = res.result.error { 451 | observer.onError(error) 452 | } 453 | observer.onNext(res.result.value) 454 | observer.onCompleted() 455 | }) 456 | return AnonymousDisposable{ 457 | re.cancel() 458 | } 459 | }) 460 | } 461 | } 462 | --------------------------------------------------------------------------------