探索之旅:原生API

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
查看查看299 回复回复4 收藏收藏 分享淘帖 转播转播 分享分享 微信
查看: 299|回复: 4
收起左侧

探索之旅:原生API

[复制链接]
Ding 发表于 2016-10-21 09:04:46 | 显示全部楼层 |阅读模式
快来登录
获取优质的苹果资讯内容
收藏热门的iOS等技术干货
拷贝下载Swift Demo源代码
订阅梳理好了的知识点专辑
本帖最后由 Ding 于 2016-10-25 13:29 编辑

其实,Cocoa的原生API很好用,且越来越好用,今天以网络请求为例领略一下。

探索之旅:原生API

探索之旅:原生API - 敏捷大拇指 - 探索之旅:原生API


iOS开发里的网络请求一般用第三方库,比如OC里的ASIHTTPRequest、AFNetWorking,Swift里的Alamofire等,数据解析有JSONKit、SwiftJson等。这些第三方库都很好用。

有一天,你发现ASI不再更新了,AFN从2.X升级到3.X,用法大大改变了,自己的项目里数据解析转换其实只要几个基于JSONSerialization的轻巧的函数就够用了。

如果前期没有封装过网络请求,工程里各处的ASI、AFN请求,到苹果强制要求支持IPv6的时候,你网上一查网络请求要基于URLSession来做了,不管是不是真的,你还是准备把所有的网络请求都用AFN3.X来做了。毕竟ASI是基于core foundation做的封装,AFN 3.0之前是基于URLConnection做的封装,这貌似都不保险。

更新这些库容易,也就简单用一下cocoaPods。但更新后工程里分散于各处的网络请求代码都发出了红色怒吼,你得逐个改一遍不是,重复、单调、不能忍。

看来封装是好的,现在一封装,以后第三方API一变,只需要在这个封装的文件里改改就行了。改一处,比改多处省事多了。

封装也很简单,虽然看别人都用了单例模式什么的,但你发现其实只要写一个类,里边来几个静态方法就成了。

看看自己的项目,完全没有上传下载,就是GET和POST啊,得了,就写个简单的方法:

[Swift] 纯文本查看 复制代码
/**
     Http request
     - parameter method:       GET, POST and so on
     - parameter absolutePath: host + path
     - parameter parameters:   can be nil
     - parameter timeout:      default is 30 seconds
     - parameter completion:   if failed, error will be a hint message and data will be nil
     */
    public static func request(_ method:HttpMethod = .GET,
                               absolutePath:String,
                               parameters:[String : AnyObject]? = nil,
                               timeout: TimeInterval = 30,
                               completion:@escaping (_ error:NSError?, _ data:[String : AnyObject]?)->Void)


考虑到使用的方便,可以只传入相对接口地址就行,再写一个吧:

[Swift] 纯文本查看 复制代码
/**
     Http request
     - parameter method:     GET, POST and so on
     - parameter host:       host
     - parameter path:       can be connected by parameters, e.g. "/mobileserver/searchKey.Do?key=hell0"
     - parameter parameters: can be nil
     - parameter timeout:    default is 30 seconds
     - parameter completion: if failed, data will be nil and error be generated
     */
    public static func request(_ method:HttpMethod = .GET,
                       host:String = host,
                       path:String,
                       parameters:[String : AnyObject]? = nil,
                       timeout: TimeInterval = 30,
                       completion:@escaping (_ error:NSError?, _ data:[String : AnyObject]?)->Void)


下边这个的实现只是简单调用上边那个。上边那个怎么实现呢?太简单了,用一下最新版的AlamoFire吧(实现代码略,后边看原生的实现)。写完,测试,版本迭代,过了好几个版本,一切美好。

后来,你看了AFN和AlamoFire的源码,化繁就简,发现它们只不过是对原生的URLRequest、URLSession的封装啊。而URLRequest、URLSession的用法比它们本身也复杂不到哪里去,几乎一样简洁,心血来潮,自己来实验一把。上边的函数的实现变成了这样:

[Swift] 纯文本查看 复制代码
/**
     Http request
     - parameter method:       GET, POST and so on
     - parameter absolutePath: host + path
     - parameter parameters:   can be nil
     - parameter timeout:      default is 30 seconds
     - parameter completion:   if failed, error will be a hint message and data will be nil
     */
    public static func request(_ method:HttpMethod = .GET,
                               absolutePath:String,
                               parameters:[String : AnyObject]? = nil,
                               timeout: TimeInterval = 30,
                               completion:@escaping (_ error:NSError?, _ data:[String : AnyObject]?)->Void) {
        
        if let url = URL(string: absolutePath) {
            
            // You can implement with Apple's native api such as URLSession or some third library such as Alamofire
            
            //  Used Apple's native api here
            
            var request = URLRequest(url: url)
            request.timeoutInterval = timeout
            request.httpMethod = method.rawValue;
            if let parData = data(with: parameters as AnyObject?) {
                request.httpBody = parData
            }
            
            dLog(combinedString(with: absolutePath, parameters: parameters))
            
            let session = URLSession.shared
            let task = session.dataTask(with: request, completionHandler: { (data, response, error) in
                DispatchQueue.main.async {
                    guard let _:Data = data, let _:URLResponse = response , error == nil else {
                        completion(error as NSError?, nil)
                        return
                    }
                    
                    if let dictionary = JSON(with: data) {
                        completion(nil, dictionary as? [String : AnyObject])
                    } else {
                        let hint = "can't parse response data -> dictionary"
                        let error = NSError(domain: hint, code: -2, userInfo: nil)
                        completion(error, nil)
                    }
                }
            }) 
            task.resume()
            
        } else {
            let error = NSError(domain: "url error", code: -1, userInfo: nil);
            completion(error, nil)
        }
    }
}


写完,测试,版本迭代,过了好几个版本,一切美好。

细节:combinedString函数,是自己写的,用来把接口地址和字典参数拼接成一个字符串,方便调试,解决后台哥们要具体URL的事。实现如下:

[Swift] 纯文本查看 复制代码
/**
 Combine URL and parameters as a String
 - parameter URLString:  e.g. "https://www.test.com"
 - parameter parameters: e.g. ["key": "value"]
 - returns: e.g. "https://www.test.com?key=value"
 */
public func combinedString(with URLString: String, parameters: [String: AnyObject]?) -> String {
    let parString = string(with: parameters as AnyObject?)
    var urlString = URLString
    if urlString.hasSuffix("/") {
        urlString = urlString[0...urlString.length - 2]
    }
    if parString == nil {
        return URLString
    }
    var parStr = parString!
    var result = URLString
    result.append("?" as Character)
    if parStr.hasPrefix("{") {
        parStr = parStr[1...parStr.length-1]
    }
    if parStr.hasSuffix("}") {
        parStr = parStr[0...parStr.length-2]
    }
    parStr = parStr.replacingOccurrences(of: ":", with: "=")
    parStr = parStr.replacingOccurrences(of: ",", with: "&")
    parStr = parStr.replacingOccurrences(of: "\"", with: "")
    result.append(parStr)
    return result
}


dLog,JSON(with: data),string(with: parameters as AnyObject?),urlString[0...urlString.length - 2],这都是怎么回事?

这些都是自己写的关于日志、数据转换、字符串操作的东东,简单、有趣。有兴趣可以看《Swift 小巧库》,里边有个GitHub链接:iOSBaseProject。


写着写着,慢慢就多起来,应阿牛哥之请,弄了个海淘贴:探索之旅。可以去订阅。






都看到这里了,就把这篇资料推荐给您的好朋友吧,让他们也感受一下。

回帖是一种美德,也是对楼主发帖的尊重和支持。

*声明:敏捷大拇指是全球最大的Swift开发者社区、苹果粉丝家园、智能移动门户,所载内容仅限于传递更多最新信息,并不意味赞同其观点或证实其描述;内容仅供参考,并非绝对正确的建议。本站不对上述信息的真实性、合法性、完整性做出保证;转载请注明来源并加上本站链接,敏捷大拇指将保留所有法律权益。如有疑问或建议,邮件至marketing@swifthumb.com

*联系:微信公众平台:“swifthumb” / 腾讯微博:@swifthumb / 新浪微博:@swifthumb / 官方QQ一群:343549891(满) / 官方QQ二群:245285613 ,需要报上用户名才会被同意进群,请先注册敏捷大拇指

嗯,不错!期待更多好内容,支持一把:
支持敏捷大拇指,用支付宝支付10.24元 支持敏捷大拇指,用微信支付10.24元

评分

参与人数 1金钱 +10 贡献 +10 专家分 +10 收起 理由
Anewczs + 10 + 10 + 10 32个赞!专家给力!

查看全部评分

本帖被以下淘专辑推荐:

Anewczs 发表于 2016-10-21 09:40:32 | 显示全部楼层
写得流畅,一气呵成。说明这一个技术点的思路已经炉火纯青。
 楼主| Ding 发表于 2016-10-21 09:51:26 | 显示全部楼层
Anewczs 发表于 2016-10-21 09:40
写得流畅,一气呵成。说明这一个技术点的思路已经炉火纯青。

兴趣已浓,浸淫既久,花儿就开了。
转行的 发表于 2016-10-21 21:53:51 | 显示全部楼层
楼主可以开教程了
 楼主| Ding 发表于 2016-10-27 17:01:31 | 显示全部楼层
转行的 发表于 2016-10-21 21:53
楼主可以开教程了

应阿牛之情,弄了海淘帖了。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

做任务,领红包。
我要发帖

分享扩散

都看到这里了,就把这资料推荐给您的好朋友吧,让他们也感受一下。
您的每一位朋友访问此永久链接后,您都将获得相应的金钱积分奖励
热门推荐

合作伙伴

Swift小苹果

  • 北京治世天下科技有限公司
  • ©2014-2016 敏捷大拇指
  • 京ICP备14029482号
  • Powered by Discuz! X3.1 Licensed
  • swifthumb Wechat Code
  •   
快速回复 返回顶部 返回列表