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大家可以看看
四. 项目地址
最后把项目分享出来供大家批评指正,欢迎交流讨论,我的QQ:284485487
项目地址:https://github.com/waitwalker/QQNews
网友评论