本人是个狂热的体育迷,篮球、足球、网球各种比赛都经常关注(死忠科密现变身湖密、皇马球迷、费德勒球迷),平时上班的时候每次想关注一下NBA比分都特别麻烦,拿起手机=>解锁=>打开app,每次工作忙的时候都觉得操作特别复杂。于是我想到了TodayWidget,直接锁屏状态就可以关注比分。然后我去看了一下虎扑、腾讯NBA、新浪体育,发现居然都没有这个功能。作为一个程序员,这简直不能忍,于是我就着手自己做了一个。先上一个成品图看看效果:
瞬间方便了很多,每次想看比分的时候只需要左滑屏幕即可。接下来讲一下具体的开发过程(主要讲TodayWidget的开发,主程序由于不叫简单这里略过,有问题可以问我),也非常简单(此文章是以Swift为例,OC的如果有需求我会加上来)。
一、接口
我的接口都是抓的新浪体育的,抓包工具用的Charles,具体使用方法可以去百度,使用也很简单,这里就不详细介绍了。
二、创建TodayWidget的任务
打开已经创建好的工程,选择 File>New>Target> Today Extension ,操作见图2-1、图2-2
创建完成之后会发现工程里多了一个TodayWidget的任务,如图2-3
然后运行程序,将创建的这个工程添加到TodayWidget,会发现模拟器已经有了我们创建的TodayWidget。
三、更改TodayWidget布局
在NSExtensionContext中,新添了widgetLargestAvailableDisplayMode属性,来确认当前widget是展开还是折叠状态。所以,先在TodayWidget.swift里的viewDidLoad中设置widget的mode为展开。
self.extensionContext?.widgetLargestAvailableDisplayMode = .expanded
然后,就是展开和折叠的处理了。在NCWidgetProviding协议中,新添了这么个方法widgetActiveDisplayModeDidChange
func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize) {
if activeDisplayMode == .compact {
// 折叠模式
self.preferredContentSize = maxSize
} else if activeDisplayMode == .expanded {
// 展开模式
self.preferredContentSize = CGSize(width: 0, height: 430)
}
}
我的布局使用的是一个tableview,先创建一个tableview
tableV = UITableView(frame: CGRect(x: 0, y: 40, width: self.view.frame.size.width, height: 390), style: .plain)
tableV.delegate = self
tableV.dataSource = self
tableV.showsVerticalScrollIndicator = false
tableV.showsHorizontalScrollIndicator = false
tableV.tableFooterView = tableviewFootView()
self.tableV.register(UINib(nibName: "MatchTableViewCell", bundle: nil), forCellReuseIdentifier: "today")
self.tableV.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "noMatch")
view.addSubview(tableV)
然后,我的cell使用的是xib创建的,选择File>New>File,选择Cocoa Touch Class,如图3-1 3-2
记得勾选上xib
然后利用xib拉好控件布局,如图3-3
到这里,TodayWidget 的UI布局已经基本搭建完成。
四、数据的处理
首先,我对AFNetworking进行了一层封装
import UIKit
import AFNetworking
//import SVProgressHUD
// 请求方法 GET / POST
enum HTTPMethod {
case GET
case POST
}
class NetManager: AFHTTPSessionManager {
static let shared: NetManager = {
// 实例化对象
let instance = NetManager()
// 设置响应反序列化支持的类型
instance.responseSerializer.acceptableContentTypes?.insert("text/plain")
return instance
}()
func request(method: HTTPMethod = .GET, URLString: String, parameters: [String:Any]?, completion:@escaping (_ response: Any?,_ isSuccess: Bool) -> Void) {
// 成功回调
let success = {(task: URLSessionTask, json: Any?) -> () in
guard let result = (json as! [String:Any])["result"] as? [String:Any] else {
return
}
// 错误码
let statusCode = (result["status"] as! [String:Any])["code"] as! Int
// 错误信息
let msgStr = (result["status"] as! [String:Any])["msg"] as! String
if statusCode == 0 {
completion(json as Any?, true)
} else {
// SVProgressHUD.showError(withStatus: msgStr)
print(msgStr)
completion(json as Any?, false)
}
}
//失败回调
let failure = {(task: URLSessionDataTask?, error: Error) ->() in
print("网络请求错误\(error)")
completion(nil, false)
}
if method == .GET {
get(URLString, parameters: parameters, progress: nil, success: success, failure: failure)
}else{
post(URLString, parameters: parameters, progress: nil, success: success, failure: failure)
}
}
}
然后再在TodayWidget.swift里请求数据,数据请求完之后刷新UI
NetManager.shared.request(URLString: urlStr, parameters: nil) { (response, isSuccess) in
if isSuccess
{
let currentDate = ((response as! [String:Any])["result"] as! [String:Any])["begin"] as! String
let dataDic = ((response as! [String:Any])["result"] as! [String:Any])["data"]
let fullDict = (dataDic as! [String:Any])["full"] as! [[String:Any]]
let curDict = (dataDic as! [String:Any])["cur"] as! [[String:Any]]
let preDict = (dataDic as! [String:Any])["pre"] as! [[String:Any]]
// 没有正在打的比赛
if curDict.count == 0
{
for matchDict in fullDict
{
if (matchDict["date"] as! String) == currentDate
{
self.dataArr?.append(matchDict)
}
}
} else {
for matchDict in curDict
{
if (matchDict["date"] as! String) == currentDate
{
self.dataArr?.append(matchDict)
}
}
for matchDict in fullDict
{
if (matchDict["date"] as! String) == currentDate
{
self.dataArr?.append(matchDict)
}
}
}
// 今天没有比赛
if self.dataArr?.count == 0
{
self.dataArr = preDict
}
self.tableV.reloadData()
}
}
至此,TodayWidget的功能基本完成了。
完整代码请点我