美文网首页
Swift技能总结

Swift技能总结

作者: Little_Dragon | 来源:发表于2016-05-10 09:26 被阅读480次

    技能 1. 关于自定义标记

    对于OC中 我们想在DEBUG状态下做事情,但是不在 RELease中实现的时候,我们一般是定义宏,来实现,一般写在.pch文件中. 代码如下

    #ifdef DEBUG
    #define LXLLog(...) NSLog(@"%s\n %@\n\n", __func__, [NSString stringWithFormat:__VA_ARGS__])
    #else
    #endif
    

    对于Swift中,由于没有了宏定义这个一个功能,我们只能自己建造标记来定义,什么时候是 DEBUG,什么时候是RELEASE. 可以利用 方法来定义 对用的console 语句

    // T指泛型,可由可无,任意类型. 此方法,可以输出对应的文件, 方法名, 以及行号
    func LXLLog<T>(message: T, file: String = __FILE__, method: String = __FUNCTION__, line: Int = __LINE__)
    {
        #if LXL_DEBUG
            print("\((file as NSString).lastPathComponent)[\(line)], \(method): \(message)")
        #endif
    }
    

    但只是定义这么一个语句是不被使用的, 对已这个带有标记的语句, 要进行再Swift中注册说明

    Snip20160504_2.png

    技能2: 关于SBRefrence 也就是 Storyboard refrence的使用

    Snip20160504_5.png
    Snip20160504_6.png
    Snip20160504_7.png

    对于SBRefrence 的使用比较好, 可以很好的改变程序的结构,但是又不影响程序的正常使用.

    技能3: Swift中main函数的消失

    官方解释:
    In Xcode, Mac templates default to including a “main.swift” file, but for iOS apps the default for new iOS project templates is to add @UIApplicationMain to a regular Swift file. This causes the compiler to synthesize a mainentry point for your iOS app, and eliminates the need for a “main.swift” file.

    Swift项目中添加了@UIApplicationMain 到swift文件中,使得编译器合成了一个app入口,所以不需要main.swift文件


    Snip20160504_9.png

    当然我们也可以手动创建程序的入口 main 函数:
    1.注销掉 @UIApplicationMain

    Snip20160504_10.png

    2.手动创建名字为main的文件

    Snip20160504_11.png
    import Foundation
    import UIKit
      UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(UIApplication), NSStringFromClass(AppDelegate))
    

    `

    技能4: 对于便利构造器(比较方便的构造器, convenience)的使用

    对已一般对象的初始化, 我们经常使用 init() 进行初始化, 当然有时候我们会进行 对已经初始化的对象 添加新的属性, 对于 便利构造器而言, 添加属性可以重写 init()方法进行添加, 这种以 init 方法开头的重写方法, 在Swift中我们称之为 便利构造器, 它的使用必须 调用本类的指定构造器 也就是 必须 对本类所有 属性进行初始化才可以使用.
    Swift中 对于以 init()作为初始化的方法, 没有返回值, 默认返回self, OC中是有返回值得, 并且确保 已经初始化父类属性,才可以使用

    还有一种构造方法称之为 中 , 内部创建对象, 并且对于对象的属性进行初始化, 并返回对象, 起始就是 对象建立的过程, 进行了二次封装而已

    /*
            如果想给系统的类新增构造方法, 那么只能新增一个便利构造方法
            如果构造方法是以 init 开头, 那么该构造方法是一个指定构造方法
            如果构造器方法的 init 前面还有 convenience, 那么这个构造方法 就是一个 遍历构造方法
            
            指定构造器和 便利构造 区别:
            指定构造器:
                必须初始化当前类的所有属性
            便利构造器:
                不用初始化当前类的所有属性, 但是它依赖于当前类中的其他构造方法 -- >其他构造方法已经 进行了类的初始化
            在开发中, 不要随便定义便利构造器,只有需要提供一个方法快速
        */
        convenience init(imageName: String , backgroudImageName: String){
            self.init()
            setImage(UIImage(named: imageName), forState: .Normal)
            setImage(UIImage(named: imageName + "_highlighted"), forState: .Highlighted)
            setBackgroundImage(UIImage(named: backgroudImageName), forState: .Normal)
            setBackgroundImage(UIImage(named: backgroudImageName + "_highlighted"), forState: .Highlighted)
            sizeToFit()
        }
    

    技能4. 命名空间的使用

    对于Swift中不可以根据字符串来创建对应的类, 必须借助于命名空间才可以创建对应的类 其中格式有: "空间名称"+"."+"类名" 并且确定类名必须存在才可.

    当然OC中可以直接创建. 因为OC没有空间命名这么一个概念, 所有文件之间没有联系, 只能通过 导入 import 才可以使用

    但是Swift中, 在同一个project中处于相同的工作空间, 具有相同的命名空间,对于新创建的类, 必须确定其命名空间才可以使用
    这个命名空间 一般就是 自己创建应用的名称
    命名空间是哪一个那? 图例说明:

    Snip20160506_1.png

    代码中的获取:

      // 1. 获取当前应用程序的命名空间
    // 在info 中 查询 对应 "CFBundleExecutable"的值,取出, 这里使用 guard 是为了解包. 
            guard let nsp = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] as? String else{
                return
            }
            print(nsp)
    

    获取到 对应的命名空间, 就可以 建立对应的 类的对象了, 这里并不是简单的获取类名而已 , 由字符串创建对应的类

     // 注意: 在Swift中想通过字符串创建类, 必须加上命名空间
            guard let cls: AnyClass = NSClassFromString(nsp + "." + (childControllerName ?? "")) else{
                return
            }
    

    使用类创建对象, 必须先进行类的对象, 说明类的类型, 方可使用,,, as

    guard let clsType = cls as? UIViewController.Type else {
                return
            }
    // 对于这种以类型 进行创建的对象, 只能使用 init() 创建
            let childController = clsType.init()
    

    此时, 已经创建对应类型的 控制器, 可以进行使用了

    技能5: 动态加载控制器. OC Swift 都可以使用

    这里所用的思想, 就是 对于控制器的加载, 不能仅仅 依靠的固定的模式, 要将其统一到一个可以控制器的文件中 进行加载, 这样我们 只要通过改变文件, 就可以改变控制器的加载, 让程序处于不同的展示. 对于这样的情况, 我们可以让程序 下载对应的控制器文件, 然后根据文件 加载对应的控制器, 这里我们需要考虑网速的问题, 但是, 如果没有网, 我们加载个屁

    我们通过 plist文件进行加载:
    这里我不在重复说明plist文件中 JSON 数组的组成 , 对于Swift创建空文件,内部进行填充数据即可.

    Snip20160506_2.png
    // 1.获取JSON文件路径
            let path = NSBundle.mainBundle().pathForResource("MainVCSettings", ofType: "json")!
    // 2.加载JSON数据
     let data = NSData(contentsOfFile: path)!
    // 3.序列号JSON数据, 这里使用try? 来捕获异常,发生异常返回null, 使用guard,来解包,没有解包返回else
     guard let objc = try? NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) else {
                addChildViewController("HomeTableViewController", title: "首页", imageName: "tabbar_home")
                addChildViewController("MessageTableViewController", title: "消息", imageName: "tabbar_message_center")
                addChildViewController("NullViewController", title: "", imageName: "")
                addChildViewController("DiscoverTableViewController", title: "发现", imageName: "tabbar_discover")
                addChildViewController("ProfileTableViewController", title: "我", imageName: "tabbar_profile")
                return
            }
    // 4. 类型确认
     guard let array = objc as? [[String: AnyObject]] else {
                return
            }
    // 遍历 创建
        for dict in array {
                addChildViewController(dict["vcName"] as? String, title: dict["title"] as? String, imageName: dict["imageName"] as? String  
            }
    

    技能6: 对于自定义控件中的问题 code创建问题

    这里需要说明, 对于初始化控件, 一般都是两种方式: 1. 纯代码, 2. xib 或者SB创建.

    required init?(coder aDecoder: NSCoder) {
    //        fatalError("init(coder:) has not been implemented")
            super.init(coder: aDecoder)
            setup()
        }
    

    上述方法中 注销的语句,指的是致命错误方法,, 会直接导致应用的崩溃的
    因为在Swift中, 推荐要么使用纯代码,要么使用文件进行创建
    一旦我注销掉, 就意味着, 两种方式我都可以进行创建的

    Snip20160506_3.png

    技能7: 核心动画的使用. CABaseAnimation

    同OC用法一致, 先设置需要 改变的属性:
    animationWithKeyPath: ""
    这里有多个属性和一进行选择:

    transform.scale = 比例轉換
    
        transform.scale.x = 闊的比例轉換
    
        transform.scale.y = 高的比例轉換
    
        transform.rotation.z = 平面圖的旋轉
    
        opacity = 透明度
    
        margin
    
        zPosition
    
        backgroundColor    背景颜色
    
        cornerRadius    圆角
    
        borderWidth
    
        bounds
    
        contents
    
        contentsRect
    
        cornerRadius
    
        frame
    
        hidden
    
        mask
    
        masksToBounds
    
        opacity
    
        position
    
        shadowColor
    
        shadowOffset
    
        shadowOpacity
    
        shadowRadius
    

    fromValue , 起始动画位置
    toVaue: 终止动画位置
    removedOnCompletion: 动画完成后是否回到起始状态, 也有防止动画中断的意思在理面
    duration: 动画时长
    repeatCount: 动画重复次数

    动画创建完毕后就能加入图层了

    func startAnimation() {
            // 1.创建动画
            let anim = CABasicAnimation(keyPath: "transform.rotation")
            
            // 2.设置动画属性
            anim.toValue = 2 * M_PI
            anim.duration = 5.0
            anim.repeatCount = MAXFLOAT
            
            // 告诉系统不要自动移除动画
            anim.removedOnCompletion = false
            
            // 3.将动画添加到图层
            imageView.layer.addAnimation(anim, forKey: nil)
        }
    
    

    技能8: 对于分类的建立

    对于OC中 , 有专门的分类建立, Category.
    但是对于Swift中, 建立分类必须自己建立独立文件, 自己填写继承

    Snip20160509_1.png

    因为Swift 是全局性的文件创建, 命名空间,只有加入特定词汇 private, 才能是私有属性, 所以这里的 分类,可以说是分类, 也可以说是继承吧, 对于此种的方法, 同分类的使用方法是一样的.
    对于一些合并类属性, 以及一些可以封装类属性, 皆可以用分类组成, 也可以用自定义组成.

    对于分类 和 继承, 一个重要的区别就是, 继承是重写已经有的方法, 分类是为了添加没有的方法

    技能9: 对于Swift尽量使用SB, 不要使用xib

    Swift 中 要求尽量使用sb 去 图形化创建界面 而不要使用xib', 这点从 launch由以前的 xib到现在的 sb 就可以看得出来
    这一点又有一些矛盾, 对于创建过程 , 先找xib 在进行纯码创建

    相关文章

      网友评论

          本文标题:Swift技能总结

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