swift编写--仿腾讯新闻&Charles抓包工具使用

swift的版本稳定性和兼容性有了很大提升,开发效率比objective-c要高(别人说的,哈哈),苹果也力推swift的发展,未来也是苹果的主要开发语言.
swift3.0+时候苹果SDK接口就相对稳定了,于是乎利用空闲时间自己仿照腾讯新闻,写了一个小app.主要开发语言用的纯swift,数据接口主要抓取的是腾讯新闻数据,这是后面要说网络抓包问题.
一. 项目的主要结构
项目主要结构分为四大块:1)新闻, 2)推荐, 3)直播, 4)我; 项目中的资源图片大都是从腾讯新闻ipa中获取
新闻页面
推荐页面
直播页面
以上页面由于和腾讯的太像,"简叔"意思在改改,大家需要的拷贝代码,自己跑起来看看吧.

我的页面

二 .项目的组织结构
项目采用MVVM模式编写开发
2.1项目组织结构

项目组织架构

2.2 数据获取及处理
各层负责各层的业务处理.数据回调一般用闭包实现.网络层用的是Alarmfire,数据解析用的是SwiftyJSON

// MARK: - 获取要闻列表
    typealias importNewsListCallBack = (_ ipormtNewsListArray:NSMutableArray)->Void
    func getImportNewsListData(callBack:@escaping importNewsListCallBack) -> Void
    {
        let URI:String = "getQQNewsUnreadList?apptype=ios&startarticleid=&__qnr=1f08e8d71890&global_info=0%7C&omgid=014f6bb2bb7c904d07aad9dcff6aabd976f1001011221e&idfa=30216CDE-F722-49CF-84A2-15EDEE3BB30E&qqnews_refpage=QNCommonListChannelVideoController&isJailbreak=0&appver=10.3.2_qqnews_5.3.7&network_type=wifi&device_model=iPhone7%2C1&omgbizid=e6034a6a2850844febd8b82c1e5dc7b29290006011250f&screen_height=736&devid=7C632112-BA40-425A-8610-780904BF2C5B&screen_scale=3&screen_width=414&store=1&activefrom=icon";
        let URLString = kHost + URI;
        print("请求地址",URLString);
        Alamofire.request(URLString, method: .post, parameters: nil, encoding: URLEncoding.default, headers: nil).responseJSON { (response) in
            switch response.result.isSuccess
            {
            case true:
                
                if let value = response.result.value
                {
                    let json = JSON(value);
                    let dataArray = NSMutableArray();
                    
                    if let newsList = json["newslist"].array
                    {
                        for (subJson:JSON) in newsList
                        {
                            let importNewsModel = ETTImportNewsModel()
                            importNewsModel.title = JSON["title"].string
                            importNewsModel.thumbnails = JSON["thumbnails"].array
                            if let string = JSON["thumbnails"].array?.first?.rawString()
                            {
                                importNewsModel.thumbnailsString = string
                            }
                            importNewsModel.thumbnails_big = JSON["thumbnails_big"].array;
                            importNewsModel.thumbnails_qqnews = JSON["thumbnails_qqnews"].array;
                            importNewsModel.thumbnails_qqnews_photo = JSON["thumbnails_qqnews_photo"].array;
                            importNewsModel.bigImage = JSON["bigImage"].array
                            importNewsModel.imagecount = JSON["imagecount"].intValue
                            if let bigString = JSON["thumbnails_qqnews_photo"].array?.first?.rawString()
                            {
                                importNewsModel.thumbnailsBigString = bigString
                            }
                            importNewsModel.videoTotalTime = JSON["videoTotalTime"].string
                            importNewsModel.source = JSON["source"].string
                            importNewsModel.videoNum = JSON["videoNum"].intValue
                            dataArray.add(importNewsModel)
                        }
                    }
                    callBack(dataArray)
                }
                break
                
            case false:
                break
            }
        }
    }

2.3 项目中用到的scrollView 上下联动
顶部是一个scrollView,中间内容也是一个scrollVIew,中间的滚动带动上部标题的滚动;上部标题按钮的点击触发中间页面到指定页面
初始化顶部

// MARK: - 设置顶部titleView
    func setupTopViews() -> Void
    {
        //搜索按钮
        let searchButton = UIButton()
        searchButton.setImage(kImage(named: "search_icon_btn_black"), for: UIControlState.normal)
        searchButton.setImage(kImage(named: "night-search_icon_btn_black"), for: UIControlState.highlighted)
        searchButton.frame = CGRect(x: -10, y: 0, width: 30, height: 44)
        searchButton.addTarget(self, action: #selector(searchButtonAction(button:)), for: UIControlEvents.touchUpInside)
        self.navigationItem.leftBarButtonItem = UIBarButtonItem.init(customView: searchButton);
        
        //添加按钮
        let addButton = UIButton()
        addButton.setImage(kImage(named: "timeline_add_Channel_black"), for: UIControlState.normal)
        addButton.setImage(kImage(named: "night-timeline_add_Channel_white"), for: UIControlState.highlighted)
        addButton.frame = CGRect(x: 0, y: 0, width: 30, height: 44)
        addButton.addTarget(self, action: #selector(addButtonAction(button:)), for: UIControlEvents.touchUpInside)
        self.navigationItem.rightBarButtonItem = UIBarButtonItem.init(customView: addButton);
        
        
        let titleContentView = UIView(frame: CGRect(x: 0, y: 0, width: kScreenWidth - 30 * 2 - 30 * 2, height: 44));
        titleContentView.backgroundColor = UIColor.white;
        
        
        titleArray = NSArray(objects: "要闻","视频","北京","财经","娱乐","体育","NBA","汽车","科技","社会","军事","国际","时尚","游戏","图片","数码","电影","教育","美容","综艺","韩流","足球","宠物","政务");
        
        titleScrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: titleContentView.frame.size.width, height: 44));
        titleScrollView?.contentSize = CGSize.init(width: CGFloat((titleArray.count)) * kButtonWidth, height: 0);
        titleScrollView?.isScrollEnabled = true;
        titleScrollView?.isPagingEnabled = true;
        titleScrollView?.showsHorizontalScrollIndicator = false;
        self.navigationItem.titleView = titleScrollView;
        
        lineView = UIView(frame: CGRect(x: 0, y: 42, width: kButtonWidth, height: 2));
        lineView?.backgroundColor = kLineViewBackgroundColor;
        titleScrollView?.addSubview(lineView!);
        
        buttonArray = NSMutableArray();
        
        for index in 0...(titleArray.count - 1) {
            
            let buttonX:CGFloat = CGFloat(index) * kButtonWidth;
            let buttonY:CGFloat = 0;
            let buttonWidth:CGFloat = kButtonWidth;
            let buttonHeight:CGFloat = 40.0;
            let button = UIButton(frame: CGRect(x: buttonX, y: buttonY, width: buttonWidth, height: buttonHeight));
            button.setTitle(titleArray[index] as? String, for: UIControlState.normal);
            button.setTitleColor(kSelectedButtonTitleColor, for: UIControlState.selected);
            button.setTitleColor(kNormalButtonTitleColor, for: UIControlState.normal);
            button.tag = index;
            button.addTarget(self, action: #selector(buttonAction(button:)), for: UIControlEvents.touchUpInside);
            button.titleLabel?.font = UIFont.systemFont(ofSize: kSelectedButtonTitleFontSize);
            titleScrollView?.addSubview(button);
            buttonArray.add(button);
        }
    }

顶部按钮标题的事件回调

// MARK: - 顶部titleView按钮的点击事件回调
    @objc func buttonAction(button:UIButton) -> Void
    {
        button.isSelected = true;
        let subviews = middleScrollView?.subviews[button.tag];
        middleScrollView?.contentOffset = CGPoint(x: (subviews?.frame.origin.x)!, y: (subviews?.frame.origin.y)!);
        for index in 0...(buttonArray.count - 1) {
            let tempButton:UIButton = buttonArray[index] as! UIButton;
            if tempButton.tag != button.tag
            {
                tempButton.isSelected = false;
            }
        }
    }

通过UISrcollView的代理回调方法实现联动

// MARK: - UIScrollViewDelegate
    func scrollViewDidScroll(_ scrollView: UIScrollView)
    {
        if scrollView == middleScrollView 
        {
            let pageIndex:Int = Int(scrollView.contentOffset.x / scrollView.frame.size.width + 0.5);
            for index in 0...((buttonArray.count) - 1) {
                
                if index == pageIndex
                {
                    let button:UIButton = buttonArray[index] as! UIButton;
                    button.isSelected = true;
                    button.titleLabel?.font = UIFont.systemFont(ofSize: kSelectedButtonTitleFontSize);
                    
                    UIView.animate(withDuration: 0.5, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 5.0, options: UIViewAnimationOptions.curveEaseOut, animations: {
                        
                        var lineViewFrame = self.lineView?.frame;
                        lineViewFrame?.origin.x = button.frame.origin.x;
                        self.lineView?.frame = lineViewFrame!;
                        
                        let toRight:CGFloat = button.frame.origin.x + button.frame.size.width;
                        let toLeft:CGFloat = button.frame.origin.x;
                        let minX:CGFloat = (self.titleScrollView?.contentOffset.x)!;
                        let maxX:CGFloat = (self.titleScrollView?.contentOffset.x)! + (self.titleScrollView?.frame.size.width)!;
                        if toRight > maxX
                        {
                            self.titleScrollView?.setContentOffset(CGPoint(x: self.titleScrollView!.contentOffset.x + (toRight - maxX), y: self.titleScrollView!.contentOffset.y), animated: true);
                        }
                        
                        if toLeft < minX
                        {
                            self.titleScrollView?.setContentOffset(CGPoint(x: (self.titleScrollView?.contentOffset.x)! + (toLeft - minX), y: (self.titleScrollView?.contentOffset.y)!), animated: true);
                        }
                        
                    }, completion: { (finished) in
                        
                    })
                    
                } else
                {
                    let button:UIButton = buttonArray[index] as! UIButton;
                    button.isSelected = false;
                    button.titleLabel?.font = UIFont.systemFont(ofSize: kNormalButtonTitleFontSize);
                }
            }
        } else if scrollView .isKind(of: UITableView.self)
        {
            return;
        }
    }

其他部分的实现大家有兴趣的可以把代码clone下拉看看

三. 数据抓取
项目中用到的数据都是实时抓取腾讯新闻客户端数据,之前添加了本地持久化数据,后来又把这部分移除了.所用到的工具主要是Charles,对于Charles使用教程和破解方法网上都有,这篇文章写得挺详细:http://www.jianshu.com/p/235bc6c3ca77大家可以看看

四. 项目地址
最后把项目分享出来供大家批评指正,欢迎交流讨论.
项目地址:https://github.com/waitwalker/QQNews

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

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,067评论 4 62
  • 不希望被别人轻视,是大家一致的想法!不论是男人还是女人!而作为女人则很容易被轻视,扎克伯格的妻子,贝克汉姆的妻子,...
    Daiaviolet阅读 269评论 0 0
  • 此刻写下三两行字。届时,我便可以告诉所有人我并非一无所有
    画龙点睛阅读 85评论 0 0
  • 美联储的最初目的: 形成“弹性货币供应”:根据经济活动的情况,扩大或收紧货币流通量。目的是让物价保持平稳,不受繁荣...
    不忘初心2017阅读 256评论 0 0