美文网首页
iOS开发-OAuth授权(下篇)

iOS开发-OAuth授权(下篇)

作者: 少少少少少少少 | 来源:发表于2017-03-16 11:10 被阅读91次
  • 获取未授权RequestToken(登录界面)
    • 按照文档发送GET请求
  • 获取已经授权RequestToken(让用户登录)
    • 截取授权回调页code=后面字符串
  • 换取AccessToken(令牌)
    • 传递已经授权RequestToken, 和其它参数
  • 守护者和可选绑定
    • guard let value = xxx else {}
      • 有效避免{}嵌套, 提高阅读性
      • 条件表达式中的变量可以在后面使用
      • 条件表达式中的变量不能在{}中使用
    • if let value = xxx {}
      • 容易形成{}嵌套
      • 条件表达式中的变量不能在后面使用
      • 条件表达式中的变量可以在{}中使用
    • 守护者和可选绑定可以添加额外条件

Swift
// 两个条件同时为false进入{}
guard let value = xxx where 条件表达式
else
{
return true
}

// 两个条件同时为true进入{}
if let value = xxx where 条件表达式
{

}
```
  • NSURLquery属性
    • 用于获取URL中的参数(?后面的内容)
  • 单例
    • dispatch
      • 原理默认dispatch_once_t等于0, 执行一次之后变为-1
        *Swift不推荐这样编写单例
swift
    static var onceToken: dispatch_once_t = 0;
    static var instance: NetworkTools?;
    class func shareInstance() -> NetworkTools
    {
        print(onceToken)
        dispatch_once(&onceToken) { () -> Void in
            instance = NetworkTools()
        }
        return instance!
    }
    ```



    + 静态常量
        * let是线程安全的
        * let只能赋值一次
        * 推荐写法

    swift
    static let shareInstance:NetworkTools = NetworkTools()
    

    + 如何在创建单例时初始化对象
        * 静态常量 + 重写构造方法
        swift
        static let shareInstance:NetworkTools = NetworkTools()
        override init() {
            print("初始化操作")
        }
        
        * 静态常量 + 闭包
        swift
        static let shareInstance:NetworkTools = {
            let t = NetworkTools()
            print("初始化操作")
            // 对T进行初始化
            return t
        }()
        
- AFN
    + Swift使用不同命名空间(不同项目)中的类需要导入头文件
    ```swift
    import UIKit
    import AFNetworking

    class NetworkTools: AFHTTPSessionManager {

        static let shareInstance: NetworkTools = {
            // 注意: 指定baseURL一定要以/结尾
           let url = NSURL(string: "https://api.weibo.com/")
           let tools =  NetworkTools(baseURL: url)
            tools.responseSerializer.acceptableContentTypes = NSSet(objects: "application/json", "text/json", "text/javascript", "text/plain") as? Set<String>
           return tools
        }()
    }
    ```

- KVC
    + key必须和属性一一对应, 否则需要重写
    ```swift
    override func setValue(value: AnyObject?, forUndefinedKey key: String) {}
    ```
    + 在构造方法中使用KVC必须先调用super.init()
    + 基本数据类型属性必须初始化, 否则会报错

- 打印对象
    + 重写CustomStringConvertible协议中的description属性
    ```swift
    override var description: String{
        let keys = ["access_token", "expires_in", "uid"]
        let dict = dictionaryWithValuesForKeys(keys)
        return "\(dict)"
    }
    ```
    + 注意Swift2.0之前该属性在Printable协议中

- 归档解归档
    + 和OC一致
    ```swift
    // 写入文件时调用
    func encodeWithCoder(aCoder: NSCoder)
    {
        aCoder.encodeObject(access_token, forKey: "access_token")
        aCoder.encodeObject(expires_in, forKey: "expires_in")
        aCoder.encodeObject(uid, forKey: "uid")
    }
    // 从文件中读取出来时调用
    required init?(coder aDecoder: NSCoder)
    {
        access_token = aDecoder.decodeObjectForKey("access_token") as? String
        expires_in = aDecoder.decodeObjectForKey("expires_in") as! Int
        uid = aDecoder.decodeObjectForKey("uid") as? String
    }
    ```
    + 注意: 开发中谁最清楚怎么做, 方法就应该在谁里面

- 路径
    - `Documents`
        - 需要保存由"应用程序本身"产生的文件或者数据,例如:游戏进度、涂鸦软件的绘图
        - 目录中的文件会被自动保存在 iCloud
        - 注意:不要保存从网络上下载的文件,否则会无法上架!

    - `Caches`
        - 保存临时文件,"后续需要使用",例如:缓存图片,离线数据(地图数据)
        - 系统不会清理 `cache` 目录中的文件
        - 就要求程序开发时,"必须提供 `cache` 目录的清理解决方案"

    - `Preference`s
        - 用户偏好,使用 `NSUserDefault` 直接读写!
        - 如果要想数据及时写入磁盘,还需要调用一个同步方法

    - `tmp`
        - 保存临时文件,"后续不需要使用"
        - `tmp` 目录中的文件,系统会自动清理
        - 重新启动手机,`tmp` 目录会被清空
        - 系统磁盘空间不足时,系统也会自动清理

- 路径优化
    + 开发中经常需要往CachesDirectory/DocumentDirectory/TemporaryDirectory中存储数据
    + 为了方便拼接路径, 化繁为简应该对拼接实现进行封装

Swift
func docDir() -> String
{
// 1.拿到文件夹路径
let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last!
// 2.拼接字符串
// 注意: pathComponents方法, 会按照字符串的/来切割字符串, 如果给定的字符串中没有/那么就直接返回给定的字符串
let temp = (self as NSString).pathComponents.last

    // 如果??前面有值, 那么??后面的代码不执行, 如果??前面没有值, 那么就执行??后面的代码
    let result = (path as NSString).stringByAppendingPathComponent(temp ?? "")

    // 3.返回结果
    return result
}

func cachesDir() -> String
{
    // 1.拿到文件夹路径
    let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomainMask.UserDomainMask, true).last!
     let temp = (self as NSString).pathComponents.last
    // 2.拼接字符串
    let result = (path as NSString).stringByAppendingPathComponent(temp ?? "")

    // 3.返回结果
    return result
}

func tmpDir() -> String
{
    // 1.拿到文件夹路径
    let path = NSTemporaryDirectory()

     let temp = (self as NSString).pathComponents.last
    // 2.拼接字符串
    let result = (path as NSString).stringByAppendingPathComponent(temp ?? "")

    // 3.返回结果
    return result
}

- `??`
    + `??`前面不为`nil`,后面不执行
    + `??`前面为`nil`, 执行后面代码

- 性能优化
    + 多次从文件中加载授权模型返回的结果一致
    + 从文件中加载模型非常消耗性能
    + 解决方案: 利用静态变量保存, 只加载一次

- 自定义UICollection布局
    + 在显示cell之前会调用prepareLayout准备布局
    + 在prepareLayout方法中修改布局
```swift
class NewfeatureLayout: UICollectionViewFlowLayout {
    // 该方法会在显示cell之前调用
    override func prepareLayout() {
        // 修改layout属性
        itemSize = UIScreen.mainScreen().bounds.size
        scrollDirection = UICollectionViewScrollDirection.Horizontal
        minimumInteritemSpacing = 0
        minimumLineSpacing = 0

        // 设置collectionView
        collectionView?.showsHorizontalScrollIndicator = false
        collectionView?.showsVerticalScrollIndicator = false
        collectionView?.bounces = false
        collectionView?.pagingEnabled = true

    }
}
  • 监听cell是否完全显示
override func collectionView(collectionView: UICollectionView, didEndDisplayingCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath){
}
  • 获取当前显示cell的索引
swift let path = collectionView.indexPathsForVisibleItems()
  • Damping动画
/*
        第一个参数: 动画时长
        第二个参数: 延迟时长
        第三个参数: 震动幅度 0.0~1.0之间, 值越小震动越厉害
        第四个参数: 动画初始速度, 值越大开始就越快
        第五个参数: 附加选项
        第六个参数: 需要执行动画代码
        第七个参数: 动画执行完毕之后的回调
        */
        UIView.animateWithDuration(2.0, delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 10, options: UIViewAnimationOptions(rawValue: 0), animations: { () -> Void in
                self.startButton.transform = CGAffineTransformIdentity
            }, completion: { (_) -> Void in
                XMGLog("动画执行完毕")
                self.startButton.userInteractionEnabled = true
        })
  • 获取用户信息
    • 保证方法单一性, 不要做过多复杂操作
    • 将主动权交给调用者
func loadUserInfo(finished: (dict: [String: AnyObject]?, error: NSError?)->())
    {

        // 断言: 用于程序员之间沟通
        // 断定access_token一定有值, 如果没有程序就会崩溃, 并且打印后面的message
        assert(access_token != nil, "必须有access_token才能使用该方法")
        assert(uid != nil, "必须有uid才能使用该方法")

        // 1.准备路径
        let path = "2/users/show.json"
        // 2.准备参数
        let parameters = ["access_token": access_token!, "uid": uid!]
        // 3.发送Get请求
        NetworkTools.shareInstance.GET(path, parameters: parameters, success: { (task, objc) -> Void in

            // 3.1.对服务器返回的数据进行安全校验
            guard let dict = objc as? [String: AnyObject] else
            {
                XMGLog("服务器没有返回数据")
                return
            }

            // 3.2从获取到的用户信息中取出昵称和头像
            self.avatar_large = dict["avatar_large"] as? String
            self.screen_name = dict["screen_name"] as? String

            // 3.3保存授权信息
//            self.saveUserAccount()
            finished(dict: dict, error: nil)

            }) { (task, error) -> Void in
                XMGLog(error)
                finished(dict: nil, error: error)
        }
    }
+ 用到闭包, 不管三七二十一先写上 `()->() ` 再做其它修改
  • 界面切换流程

  • 检查新版本

    • 思路
      • 获取当前
      • 获取以前
      • 进行比较
      • 更新以前
      • 返回结果
Swift
/// 判断是否有新版本
    private func isNewVersion() -> Bool
    {
        // 1.获取软件当前的版本号
        guard let currentVersion = NSBundle.mainBundle().infoDictionary!["CFBundleShortVersionString"] as? String else
        {
            return false
        }

        // 2.获取软件以前的版本号
        let defaults = NSUserDefaults.standardUserDefaults()
        let sandboxVersion = (defaults.objectForKey("xmg") as? String) ?? "0"

        // 3.利用软件当前的版本号和以前的版本号进行比较
        // 如果当前 > 以前  --> 新版本
        //  1.0   0.0
        if currentVersion.compare(sandboxVersion) == NSComparisonResult.OrderedDescending
        {
            NSLog("有新版本")
            // 4.如果有新版本就用当前的软件版本号更新以前的软件版本号
            defaults.setObject(currentVersion, forKey: "xmg")
//            defaults.synchronize() // iOS7以后不用写
            return true
        }

        NSLog("没有新版本")
        // 没有新版本
        return false
    }
  • 完善界面切换逻辑
    • 注意统一管理, 便于后期维护
    • 注意安全校验, 一般网络和通知都需要校验
// 发送通知, 切换到首页
 NSNotificationCenter.defaultCenter().postNotificationName(SYPChangeRootViewControllerNotification, object: self, userInfo: ["message": true])

 // 发送通知切换到欢迎界面
  NSNotificationCenter.defaultCenter().postNotificationName(SYPChangeRootViewControllerNotification, object: self, userInfo: ["message": false])

  // 监听通知切换界面
  @objc private func switchRootViewController(notice: NSNotification)
    {
//        NSLog(notice)
        // 1.取出userInfo中的message
        guard let info = notice.userInfo else
        {
            return
        }
        guard let flag = info["message"] as? Bool else
        {
            return
        }

        // 2.根据message对应的值, 决定对应的界面
        var sb = UIStoryboard(name: "Welcome", bundle: nil)
        if flag
        {
            // 跳转到首页
            sb = UIStoryboard(name: "Main", bundle: nil)
        }
        window?.rootViewController = sb.instantiateInitialViewController()!
    }

相关文章

  • iOS开发-OAuth授权(下篇)

    获取未授权RequestToken(登录界面)按照文档发送GET请求 获取已经授权RequestToken(让用户...

  • iOS开发-OAuth授权(上篇)

    OAuth授权的介绍 OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准 OAuth 的授权不会...

  • iOS开发-OAuth2.0授权

    1、什么是OAuth2.0协议? OAuth2.0(Open Authorization 2.0,开放授权)协议是...

  • iOS - OAuth授权

    如果开发者需要从第三方获取数据时,就需要获取第三方的OAuth授权,这样可以保证数据的安全,使得第三方软件既可以访...

  • oauth2.0的授权流程详解

    oauth2.0的授权流程详解 授权模式 1)oauth2.0 提供了四种授权模式,开发者可以根据自己的业务情况自...

  • 理解OAuth 2.0

    一、什么是Oauth2 Oauth是一个关于授权(authentication)的开发网络标准,允许用户授权第三方...

  • Oauth2授权码模式

    3.3 Oauth2授权码模式 3.3.1 Oauth2授权模式 Oauth2有以下授权模式: 授权码模式(Aut...

  • iOS中OAuth授权获取Access_Tolen

    iOS中OAuth授权获取Access_Tolen 在所有快速登录中差不多采用同样的授权方式获取access_To...

  • IOS中 SSO授权进行应用之间跳转(URL Schemes)

    OAuth 授权 和 SSO 授权区别: OAuth 授权 是弹出一个 网页. 缺点: 需...

  • spring security oauth2

    /oauth/authorize:授权端点。 /oauth/token:令牌端点。 /oauth/confirm_...

网友评论

      本文标题:iOS开发-OAuth授权(下篇)

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