美文网首页
网络规范开发简单练习-swift-NSURLConnection

网络规范开发简单练习-swift-NSURLConnection

作者: 金火鸟 | 来源:发表于2016-08-25 19:49 被阅读0次

    网络规范开发简单练习-swift-NSURLConnection

    虽然NSURLConnection已经很少使用,可是并不能说明它不重要,对于一个初学者来说,要想学好网络,必须从最基础的地方入手,基础牢了,在以后的学习中才能事半功倍。根基不稳,再怎么小心翼翼也抵达不到云层。

    所用接口

    //限免
    "http://iappfree.candou.com:8080/free/applications/limited?currency=rmb&page=1
    //降价
    "http://iappfree.candou.com:8080/free/applications/sales?currency=rmb&page=1
    //免费
    "http://iappfree.candou.com:8080/free/applications/free?currency=rmb&page=1

    www.bejson.com 解析

    效果

    <img src="/Users/qianfeng/Desktop/屏幕快照 2016-08-25 下午6.37.00.png" width = "120" height = "200" />
    <img src="/Users/qianfeng/Desktop/屏幕快照 2016-08-25 下午6.37.10.png" width = "120" height = "200" />
    <img src="/Users/qianfeng/Desktop/屏幕快照 2016-08-25 下午6.37.20.png " width = "120" height = "200" />

    删除Mainboard,ViewController,Info.plist中的Main函数入口,导入第三方库MJRefresh(下拉刷新),SDWebImage并设置桥接。

    • 右键项目->NewFile->ios(Source)->Header File->Save As:(输入文件名字,例如:bridgingHeader)->Create
    • 打开bridgingHeader.h导入第三方库
      (#import "UIImageView+WebCache.h"
      (#import "MJRefresh.h"
    • 桥接 ->点一下项目名->点一下左边PROJECT下的文件名 ->Build Settings ->选择All ->输入bridge搜索->Objectives-C Bridging Header->双击右侧空白区域输入->文件夹的名字/bridgingHeader.h

    桥接文件时,如果.h文件建在根项目下,直接输入文件名字即可,如果在文件夹内,则需要加入文件夹的名字,在这里我们把桥接文件建立在了文件夹内

    1.新建一个MytabBarController继承自UITabBarController

    2.打开AppDelegate.swift文件,修改里面的第一个函数application

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            window = UIWindow.init(frame: UIScreen.mainScreen().bounds)
            window?.rootViewController = MyTabBarController()
            window?.backgroundColor = UIColor.whiteColor()
            window?.makeKeyAndVisible()
            return true
        }
    

    3.

    • 新建一个BaseViewController作为所有控制器的基类,用来统一修改界面风格,现在只插入一行代码作为示范

    self.view.backgroundColor = UIColor.grayColor()

    * 新建ListViewController继承自BaseViewController
    * 新建LimitViewController,FreeViewController,SaleViewController分别继承自ListViewController
    ###4.新建一个TabBar.plist文件,用来存放MyTabBarController里的控制器内容,在文章底部自行下载源代码进行查看tabBar.plist文件,此处不再上图
    ###5.打开MytabBarController文件进行编辑
    

    override func viewDidLoad() {
    super.viewDidLoad()

        //工程名
        let proName = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] as! String
        
        //拿到plist文件路径
        let path = NSBundle.mainBundle().pathForResource("TabBar.plist", ofType: nil)!
        
        //将plist文件数据读到数组里
        let plistArr = NSArray.init(contentsOfFile: path) as! [[String : String]]
        for dic in plistArr {
            
            //拿到代表类名的字符串
            let name = proName + "." + dic["name"]!
            
            // self      Type     dynamicType
            //将字符串转成类
            let vcClass = NSClassFromString(name) as! UIViewController.Type
            
            //构造页面对象
            let vc = vcClass.init()
            
            //导航
            let nc = UINavigationController.init(rootViewController: vc)
            vc.navigationItem.title = dic["title"]
            
            //显示在tabBar上的专用按钮
            nc.tabBarItem = UITabBarItem.init(title: dic["title"], image: UIImage.init(named: dic["icon"]!), tag: 0)
            
            //将页面/导航添加到tabBarController里面
            self.addChildViewController(nc)
        }
    }
    
        
    
    ##注意:以上只是用纯代码规范化搭建了一个tabController的界面,仅作参考,读者也可以自行拖控件搭建
    ###6.新建AppModel继承自NSObject用来存放数据模型
    

    class AppModel: NSObject {

    var applicationId: String?
    var iconUrl: String?
    var name: String?
    var starCurrent: String?
    var lastPrice: String?
    var categoryName: String?
    var favorites: String?
    var shares: String?
    var downloads: String?
    var expireDatetime: String?
    var currentPrice: String?
    
    
    static func modelWith(dic: [String: AnyObject]) -> AppModel {
        let model = AppModel()
        model.setValuesForKeysWithDictionary(dic)
        return model
    }
    //如果输入了未定义的属性,则调用该方法
    override func setValue(value: AnyObject?, forUndefinedKey key: String) {
        print("您输入了未定义属性的Key:\(key)")
    }
    

    }

    ###7.新建AppCell继承自UITableViewCell并勾选xib文件,界面自行搭建,此处不再演示,cell重用标识符"qqq",需要注意的是降价页面又一个黑色的线,可以用view,背景设置为黑色(但在cell点击时,cell内的所有控件的背景色都将失去效果)
    
    ![](/Users/qianfeng/Desktop/屏幕快照 2016-08-24 下午7.50.16.png)
    
    ###8.编辑ListViewContoller文件,ListViewController放了所有控制器界面的相同部分(请先编写第9步)
    

    class ListViewController: BaseViewController {

    let limit_url = "http://iappfree.candou.com:8080/free/applications/limited?currency=rmb&page=%d"
    let sale_url = "http://iappfree.candou.com:8080/free/applications/sales?currency=rmb&page=%d"
    let free_url = "http://iappfree.candou.com:8080/free/applications/free?currency=rmb&page=%d"
    
    let tableView = UITableView()
    var dataArr = [AppModel]()
    
    var urlStr: String?
    //记录触底加载的页数
    var page = 2
        
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.frame = self.view.frame
        tableView.delegate = self
        tableView.dataSource = self
        self.view.addSubview(tableView)
        tableView.separatorColor = UIColor.redColor()
        tableView.rowHeight = 100
        tableView.registerNib(UINib.init(nibName: "AppCell", bundle: nil), forCellReuseIdentifier: "qqq")
        //闭包会捕获内部使用的实例(强引用)
        //为了防止循环引用,闭包内部通常都用弱引用
        weak var weakSelf = self
        //下拉刷新的控件
        tableView.mj_header = MJRefreshNormalHeader.init(refreshingBlock: { 
            let url = String.init(format: weakSelf!.urlStr!, 1)
            let mc = MyConnection.init(urlStr: url, target: weakSelf!, action: #selector(weakSelf!.connectionFinish(_:)),tag: 1)
            mc.start()
        })
        
        //上拉刷新控件
        tableView.mj_footer = MJRefreshAutoNormalFooter.init(refreshingBlock: { 
            let url = String.init(format: weakSelf!.urlStr!, weakSelf!.page)
            let mc = MyConnection.init(urlStr: url, target: weakSelf!, action: #selector(weakSelf!.connectionFinish(_:)),tag: 2)
            mc.start()
        })
        
        //直接进入下拉刷新状态
        tableView.mj_header.beginRefreshing()
        if let data = self.readLocal() {
            self.parseData(data)
        }
    }
    
    func connectionFinish(mc:MyConnection) -> Void {
        if mc.isFinish {
        //触底加载之后会有许多内容,然后上拉刷新恢复
            if mc.tag == 1 {
                dataArr.removeAll()
                page = 2
                self.writeTolocalWith(mc.downloadData)
            } else {
                page += 1
            }
            self.parseData(mc.downloadData)
            tableView.reloadData()
        } else {
            print("\(self)网络请求失败")
        }
        //关闭加载状态
        tableView.mj_header.endRefreshing()
        tableView.mj_footer.endRefreshing()
    }
    
    func parseData(data:NSData) -> Void {
        //json
        let dataDic = try! NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) as! NSDictionary
        let appArr = dataDic["applications"] as! [[String: AnyObject]]
        
        //字典转模型
        for appDic in appArr {
            dataArr.append(AppModel.modelWith(appDic))
        }
        
    }
    

    }

    //MARJK: 缓存
    extension ListViewController {
    //往本地存数据
    func writeTolocalWith(data: NSData) {
    //类名转成字符串
    let name = NSStringFromClass(self.dynamicType)
    //拼接完整的沙盒路径
    let path = String.init(format: "%@/Documents/%@.txt", NSHomeDirectory(),name)
    //将数据写入文件
    data.writeToFile(path, atomically: true)

    }
    
    //从本地读区数据
    func readLocal() -> NSData? {
        let name = NSStringFromClass(self.dynamicType)
        let path = String.init(format: "%@/Documents/%@.txt", NSHomeDirectory(),name)
        return NSData.init(contentsOfFile: path)
    }
    

    }

    extension ListViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return dataArr.count
    }
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("qqq", forIndexPath: indexPath) as! AppCell
    cell.customWithModel(dataArr[indexPath.row])
    return cell
    }
    }

    ###9.新建MyConnection继承自NSObject
    

    class MyConnection: NSObject {
    //MARK:属性
    //记录网址
    var urlStr: String?
    //记录下载的数据
    let downloadData = NSMutableData()

    //记录一个对象
    var target: AnyObject?
    //记录一个方法
    var action: Selector?
    
    //记录下载的状态
    var isFinish: Bool = false
    
    //标记
    var tag: Int?
    
    //记录执行网络连接的对象
    var connection: NSURLConnection?
    

    //MARK:方法
    init(urlStr: String, target: AnyObject, action: Selector, tag: Int = 0) {
    self.urlStr = urlStr
    self.target = target
    self.action = action
    self.tag = tag
    }

    //启动
    func start() -> Void {
        let url = NSURL.init(string: urlStr!)!
        let request = NSURLRequest.init(URL: url)
        UIApplication.sharedApplication().networkActivityIndicatorVisible = true
        connection = NSURLConnection.init(request: request, delegate: self)
    }
    
    func stop() -> Void {
        connection?.cancel()
    }
    
    deinit {
        UIApplication.sharedApplication().networkActivityIndicatorVisible = false
    }
    

    }

    extension MyConnection: NSURLConnectionDataDelegate {
    func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) {
    self.downloadData.length = 0
    }
    func connection(connection: NSURLConnection, didReceiveData data: NSData) {
    self.downloadData.appendData(data)
    }
    func connectionDidFinishLoading(connection: NSURLConnection) {
    self.isFinish = true
    self.target!.performSelector(action!, withObject: self)
    }
    func connection(connection: NSURLConnection, didFailWithError error: NSError) {
    self.isFinish = false
    self.target!.performSelector(action!, withObject: self)
    }
    }

    ###10.编辑LimitViewController
    

    class LimitViewController: ListViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    
        self.urlStr = self.limit_url
        
        
    }
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath) as! AppCell
        let model = dataArr[indexPath.row]
        
        
        cell.subLabel.text = self.stringFrom(model.expireDatetime!)
        
        return cell
    }
    
    func stringFrom(dataStr:String) -> String {
        //时间戳(将时间和字符串进行转化)
        let dateFormat = NSDateFormatter()
        //设置转化格式(大MM,小dd,ss后面的 .0可要可不要)
        dateFormat.dateFormat = "yyyy-MM-dd HH:mm:ss.0"
        let date = dateFormat.dateFromString(dataStr)!
        //计算时间差
        let time = Int(date.timeIntervalSinceNow)
        
        return String.init(format: "剩余:%02d:%02d:%02d", time / 3600, time % 3600 / 60, time % 60)
    }
    

    }

    ###11.编辑FreeViewController
    

    class FreeViewController: ListViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    
        self.urlStr = self.free_url
        
    }
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath) as! AppCell
        cell.subLabel.text = "我爱中国"
        return cell
    }
    

    }

    ###12.编辑SaleViewController
    

    class SaleViewController: ListViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    
        self.urlStr = self.sale_url
    }
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath) as! AppCell
        let model = dataArr[indexPath.row]
        cell.subLabel.text = String.init(format: "现价:¥%0.1f", Float(model.currentPrice!)!)
        return cell
    }
    

    }

    
    ###补充:在Info.plist文件中加入http链接的请求,读者自己比较.plist文件有什么不同,缺少的地方自己点击加入
    [点这里下载源代码](/Users/qianfeng/Desktop/LoveFree副本.zip)

    相关文章

      网友评论

          本文标题:网络规范开发简单练习-swift-NSURLConnection

          本文链接:https://www.haomeiwen.com/subject/deyasttx.html