1.用户账户模型类 UserAccount.swift
///用户账户模型
class UserAccount: NSObject, NSCoding{
//用户授权的唯一票据,用于调用微博的开放接口,同时也是第三方应用验证微博用户登录的唯一票据,第三方应用应该用该票据和自己应用内的用户建立唯一影射关系,来识别登录状态,不能使用本返回值里的UID字段来做登录识别。
@objc var access_token: String?
//access_token的生命周期,单位是秒数 TimeInterval = 0 /String?
//一旦从服务器获得过期的时间,立刻计算准确的日期
@objc var expires_in: TimeInterval = 0{
didSet{
//计算过期日期
expiresDate = Date(timeIntervalSinceNow: expires_in)
}
}
//过期日期
@objc var expiresDate:Date?
//授权用户的UID,本字段只是为了方便开发者,减少一次user/show接口调用而返回的,第三方应用不能用此字段作为用户登录状态的识别,只有access_token才是用户授权的唯一票据。
@objc var uid: String?
@objc var isRealName: Bool = false
//用户昵称
@objc var screen_name: String?
//用户头像地址(大图),180×180像素
@objc var avatar_large: String?
init(dict:[String: Any]) {
super.init()
setValuesForKeys(dict)
}
override func setValue(_ value: Any?, forUndefinedKey key: String) {}
//打印模型的描述信息
override var description: String{
let key = ["access_token", "expires_in", "expiresDate", "uid", "isRealName", "screen_name", "avatar_large"]
return dictionaryWithValues(forKeys: key).description
}
//MARK: - "键值" 归档和解档
/// 归档 - 把当前对象保存到磁盘前,将对象编码成二进制数据 - 跟网络的序列化概念很像
/// - Parameter coder: 编码器
func encode(with coder: NSCoder) {
coder.encode(access_token, forKey: "access_token")
coder.encode(expiresDate, forKey: "expiresDate")
coder.encode(uid, forKey: "uid")
coder.encode(screen_name, forKey: "screen_name")
coder.encode(avatar_large, forKey: "avatar_large")
}
/// 接档 - 从磁盘加载二进制文件,转成对象时调用 - 跟网络的反序列化很像
/// - Parameter coder: 解码器
/// - required 当前对象
/// 'required' - 当前没有继承性,所有的对象只能解档出当前的类对象
required init?(coder: NSCoder) {
access_token = coder.decodeObject(forKey: "access_token") as? String
expiresDate = coder.decodeObject(forKey: "expiresDate") as? Date
uid = coder.decodeObject(forKey: "uid") as? String
screen_name = coder.decodeObject(forKey: "screen_name") as? String
avatar_large = coder.decodeObject(forKey: "avatar_large")as? String
}
}
// 在 extension 中只允许写 便利构造函数,不允许写指定的构造函数,
// 不能定义存储型属性,定义存储型属性,会破坏类本身的结构
extension UserAccount{
// required init?(coder: NSCoder) {
//
// }
}
2.测试返回数据内容 - AFN 默认的响应格式是 JSON,会直接反序列化
func loadAccessToken(code: String, finished: @escaping requestCallBack){
let urlString = "https://api.weibo.com/oauth2/access_token"
let params : [String: Any] = ["client_id": appKey, "client_secret": appSecret, "grant_type":"authorization_code", "code": code, "redirect_uri": redirectUrl]
//测试返回数据内容 - AFN 默认的响应格式是 JSON,会直接反序列化
//如果要确认数据格式的问题
//如果是 NSNumber,则没有引号,在做 KVC 指定属性类型非常重要
//1>设置相应数据格式是二进制的
responseSerializer = AFHTTPResponseSerializer()
//2>发起网络请求
post(urlString, parameters: params, headers: nil, progress: nil, success: { _, result in
//将二进制数据转换成字符串
let json = String(data: result as! Data, encoding: .utf8)
print(json)
}, failure: nil)
}
3. JSON 转字典,字典转模型 调用函数
//JSON 字符串 -> 字典 -> 模型
func jsonToDict(){
let re = "{\"access_token\":\"2.00FdBF4*********13129a3d6Io4yB\",\"remind_in\":\"157679999\",\"expires_in\":157679999,\"uid\":\"30******31\",\"isRealName\":\"true\"}"
guard let dict = try? JSONSerialization.jsonObject(with: re.data(using: .utf8)!) else{
print("转换失败")
return
}
self.account = UserAccount(dict: dict as! [String: Any])
print(self.account)
}
4. 沙盒解档与归档
4.1 声明参数
///用户模型
var account: UserAccount?
//归档文件保存路径
private var accountURL: URL?{
guard let documentURL = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first else {return nil}
return documentURL.appendingPathComponent("account.plist")
}
/// 归档的保存路径 计算型属性 - 类似于有返回值的函数,调用的时候,语义更清晰
/// 如果在 OC 中,可以通过只读属性 / 函数的方式实现
private var accountPaths: String{
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last!
return (path as NSString).appendingPathComponent("account.plist")
}
4.2 归档保存对象
func dataToBaArchived(){
//NSKeyedArchiver.archiveRootObject(account, toFile: self.accountPath)
//保存对象 在实际开发中,一定要确认文件真的保存了 替代方法
//执行此方法 - 会调用对象的 encode 方法
guard let dataToBaArchived = try? NSKeyedArchiver.archivedData(withRootObject: account, requiringSecureCoding: false) else{
print("解档数据失败")
return
}
guard let _ = try? dataToBaArchived.write(to: self.accountURL!) else{
print("存储失败")
return
}
}
4.3 解档读取对象
func unarchiveWithData(){
// 从沙盒中解档数据,恢复当前数据 - 磁盘读写的速度最慢,不如内存读写效率高
// account = NSKeyedUnarchiver.unarchiveObject(withFile: accountPath) as? UserAccount
if let archiverData = try? Data(contentsOf: accountURL!),
let accountData = (try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(archiverData)) as? UserAccount {
account = accountData
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)