从头开始swift2.1 仿搜材通项目(七) 封装后台交互框架

火地岛的咖啡真的不错。希望在打烊前我可以写完这篇文章。
这一节我们来做本项目中的第一次网络请求,并将其封装成为自己的网络请求框架,这里使用到的有AlamofireJSONHelper,感谢这两款开发利器。
首先在pod中添加,之后不要忘记update。

pod 'Alamofire' #网络请求 https://github.com/Alamofire/Alamofire

之所以没有直接pod JSONHelper,是因为我修改了其中一点点代码,后面我会上传到git,同学们直接使用即可。
现在在Library下新建Http目录,放入修改后的JSONHelper文件,并新建一个HMRequest,后面用来封装我们网络请求的方法。


QQ20151222-1@2x.png

QQ20151222-2@2x.png

首先import,再根据大家自己公司的后台结构创建一个协议,假如接口返回的结构像这样

{
    "error": 0,
    "msg": "",
    "data": [
        {
            "id": "11012",
            "title": "这些年蹲马桶的姿势真的正确吗?",
            "link": "http://mp.weixin.qq.com/s?__biz=MjM5OTc4MDQ2NA==&mid=222471269&idx=1&sn=2835c1c321ca244b72eb40e3c3056864&scene=5#rd",
            "descr": "【健康】实际上人类发明的马桶,可能并没那么好……",
            "refinfo": "微信",
            "thumb": "http://mmbiz.qpic.cn/mmbiz/hFdY52oozXj2E7IECSq83s864qdPka6WaOaYGK0PDUcPAWq7dpibAj4qQrzFQiaRfGW4G9QhFtqowzNM2qdK6t9Q/0?wx_fmt=jpeg&wxfrom=5",
            "time": "2015-04-29"
        }
    ]
}

data里面的数据我们先不理会,我们先定义一个int的error,一个String的msg,再定义一个从json转换对象的方法。

import Alamofire

protocol HMConvertible{
    var error:Int { get set }
    var msg:String? { get set }
    static func convertFromData(data:String!) -> (Self,NSError?)
}

接下来我们写一个带参数post请求的例子,大家可以参考Alamofire的用法实现get\put等等。

class HMRequest< T:HMConvertible> {
    static func post(url :String , params: Dictionary<String,AnyObject>, completionHandler:(T?,NSError?) -> ()){
        
        //组装log,只是在控制台输出请求的地址,可以省略
        if params.count > 0{
            var str:String = "?"
            for param in params {
                str += "\(param.0)=\(param.1)&"
            }
            str = (str as NSString).substringToIndex(str.characters.count-1)
            debugPrint("--------------------post--------------------")
            debugPrint("\(url)\(str)")
        }

        Alamofire.request(.POST, url, parameters: params).responseString { response in
            //打印出接口响应的数据,可以省略
            debugPrint("result:\(response.result.value)")
            
            if response.result.isFailure {
                var domain:String?
                //对异常信息作出判断,这里简单的判断一下网络问题
                switch response.result.error?.domain{
                case NSURLErrorDomain?:
                    domain = "网络不佳"
                default :
                    domain = "未知错误"
                }
                
                let error = NSError(domain: domain!, code: (response.result.error?.code)!, userInfo: nil)
                completionHandler(nil, error)
                return
            }
            
            let(object, converError) = T.convertFromData(response.result.value)
            completionHandler(object, converError)
        }
    }
}

OK,这里我们就算封装好了,现在我们回去找个地方调用一下。恩,就这个幻灯片吧,这个可恶的广告,我早就想换了。


QQ20151222-3@2x.png

回到HomeController中的initBanner方法,还记得吗,之前我们是直接写死的图片:

        anotherBanner.images = [
            "http://pic9.nipic.com/20100817/4845745_124224113296_2.jpg",
            "http://pic26.nipic.com/20121223/11613623_164837493315_2.jpg",
            "http://pic2.ooopic.com/10/79/67/75b1OOOPIC15.jpg"
        ]

现在我们换成一个查询新闻的API,查询新闻,咦,它居然是get请求的,好吧,我们先在HMRequest中加入支持get请求:

    static func get(url :String, completionHandler:(T?,NSError!) -> ()){
        Alamofire.request(.GET, url).responseString { response in
            let(object, converError) = T.convertFromData(response.result.value)
            completionHandler(object, converError)
        }
    }
    
    static func get(url :String ,params: [String : AnyObject]?, completionHandler:(T?,NSError!) -> ()){
        Alamofire.request(.GET, url, parameters: params).responseString { response in
            let(object, converError) = T.convertFromData(response.result.value)
            completionHandler(object, converError)
        }
    }

现在我们需要创建一个类作为json序列化的对象,android那边叫实体,iOS叫模型,其实都是一回事。不过我们现在使用struct值传递,不再使用class。

struct NewsDomain: HMSerializable ,HMConvertible{

    var error: Int = 0
    
    var msg: Int = 0
    
    var data: NewsData?
    
    static func convertFromData(data: String!) -> (NewsDomain, NSError?) {
        var hm : NewsDomain?
        hm <-- data
        return (hm!,nil)
    }
    
    init(data: [String: AnyObject]) {
        error <-- data["error"]
        msg <-- data["msg"]
        self.data <-- data["data"]
    }
    
    //对应data字段,而且可以只取我们需要的字段,不需要全部解析
    struct NewsData: HMSerializable {
        var link: String? //点击跳转的url
        var thumb: String? //缩略图地址
        
        init(data: [String: AnyObject]) {
            link <-- data["link"]
            thumb <-- data["thumb"]
        }
    }
}

OK,现在万事具备,可以直接使用了,我们回到initBanner中调用:

        //请求地址
        let url = "http://apis.baidu.com/cd_boco/chinanews/testnewsapi"
        //如果需要传参
        let params = ["query":"{'device':'android','catid':1,'pagesize':3,'sid':'11142'}"]
        
        HMRequest<NewsDomain>.get(url, params: params) { (news, error) -> () in
            print(news)
        }

OK,现在运行一下看看print出什么:

Optional(sctong.NewsDomain(error: 0, msg: 0, data: nil))

news为nil,经过调试后发现,{"errNum":300202,"errMsg":"Missing apikey"},原来是这个api需要设置一下header,如果你的服务器不需要设置,那请跳过这一步:

    static func get(url :String ,params: [String : AnyObject]?, completionHandler:(T?,NSError!) -> ()){
        //设置headers
        let headers = ["apikey":"be910c69ec688ba099d0091e19c21033"]
        Alamofire.request(.GET, url, parameters: params, headers:headers).responseString { response in
            let(object, converError) = T.convertFromData(response.result.value)
            completionHandler(object, converError)
        }
    }

再次运行,发现有结果返回了,但data依然为nil,怎么回事呢?


QQ20151222-4@2x.png

我们看看服务器返回的结果:

{
    "error": 0,
    "msg": 1,
    "data": [
        {
            "id": "11012",
            "title": "这些年蹲马桶的姿势真的正确吗?",
            "link": "http://mp.weixin.qq.com/s?__biz=MjM5OTc4MDQ2NA==&mid=222471269&idx=1&sn=2835c1c321ca244b72eb40e3c3056864&scene=5#rd",
            "descr": "【健康】实际上人类发明的马桶,可能并没那么好……",
            "refinfo": "微信",
            "thumb": "http://mmbiz.qpic.cn/mmbiz/hFdY52oozXj2E7IECSq83s864qdPka6WaOaYGK0PDUcPAWq7dpibAj4qQrzFQiaRfGW4G9QhFtqowzNM2qdK6t9Q/0?wx_fmt=jpeg&wxfrom=5",
            "time": "2015-04-29"
        },
        {
            "id": "10923",
            "title": "一样东西配枸杞功效翻倍 怎样吃?",
            "link": "http://fashion.ifeng.com/a/20150421/40101843_0.shtml",
            "descr": "【药饮】原料:黑豆100克,枸杞5克,红枣10个。",
            "refinfo": "凤凰网",
            "thumb": "http://y0.ifengimg.com/cmpp/2015/04/21/08/1e430f73-3630-4e53-9ab6-6ef6c4c865e7_size25_w550_h366.jpg",
            "time": "2015-04-21"
        },
        {
            "id": "10922",
            "title": "吃烤串要烤熟 当心患\"懒汉病\"",
            "link": "http://m.news.cn/html/712/114376.html",
            "descr": "【疾病】大快朵颐的时候,一定不要忘了把肉烤熟,否则您就有可能因此患上“懒汉病”。",
            "refinfo": "新华炫闻",
            "thumb": "http://static.xhw.feedss.com/uploadfile/xwimg/89/6d/127713171_1429575260241.jpg",
            "time": "2015-04-21"
        }
    ]
}

找到原因了,data应该是一个集合,于是修改

struct NewsDomain: HMSerializable ,HMConvertible{

    var error: Int = 0
    
    var msg: Int = 0
    
    var data: [NewsData]?
    
    ///...

}

再次运行,print结果是:

Optional(sctong.NewsDomain(error: 0, msg: 1, data: Optional([sctong.NewsDomain.NewsData(link: Optional("http://mp.weixin.qq.com/s?__biz=MjM5OTc4MDQ2NA==&mid=222471269&idx=1&sn=2835c1c321ca244b72eb40e3c3056864&scene=5#rd"), thumb: Optional("http://mmbiz.qpic.cn/mmbiz/hFdY52oozXj2E7IECSq83s864qdPka6WaOaYGK0PDUcPAWq7dpibAj4qQrzFQiaRfGW4G9QhFtqowzNM2qdK6t9Q/0?wx_fmt=jpeg&wxfrom=5")), sctong.NewsDomain.NewsData(link: Optional("http://fashion.ifeng.com/a/20150421/40101843_0.shtml"), thumb: Optional("http://y0.ifengimg.com/cmpp/2015/04/21/08/1e430f73-3630-4e53-9ab6-6ef6c4c865e7_size25_w550_h366.jpg")), sctong.NewsDomain.NewsData(link: Optional("http://m.news.cn/html/712/114376.html"), thumb: Optional("http://static.xhw.feedss.com/uploadfile/xwimg/89/6d/127713171_1429575260241.jpg"))])))

已经有值了,现在修改之前写死的图片,

        HMRequest<NewsDomain>.get(url, params: params) { (news, error) -> () in
            
            var thumbUrls:[AnyObject?] = []
            for data in (news?.data)! {
                thumbUrls.append(data.thumb!)
            }
            
            anotherBanner.images = thumbUrls
            anotherBanner.startRolling()
        }

再次运行看下结果:


QQ20151222-5@2x.png

图片已经正常的显示出来了。这只是一个简单的网络请求步骤,也是一个通用的步骤,前面我们做的工作确实比较多,但这些工作都需要做第一次,在UI层调用的时候,仅仅需要这一段代码即可,并且回调中的data已是json解析好的对象直接使用,这样是不是非常方便呢?

        HMRequest<Domain>.get(url, params: params) { (data, error) -> () in
            //use data to do something
        }

OK,咖啡店打烊了,你帮我结账如何?
Git地址:https://github.com/bxcx/sctong
本节分支:https://github.com/bxcx/sctong/tree/6th_Http

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 树影斑驳,风吹沙沙。 一人一椅一书。
    生如秋叶O阅读 290评论 0 0
  • 我. 一个四川女孩. 两个孩子的宝妈。拥有一些自然会失去某种原有的。比如身材… 生完孩子我的体重从100斤直接飙升...
    朱疯疯阅读 416评论 0 0
  • 不明确的确定 存在的偏差 并无歧视性的言语 为何在意 没坦白的坦白 内心的煎熬 并无看得出的表象
    林夕静飞阅读 220评论 0 1