Swift Blog

any和 anyobject

AnyObject 可以代表任何 class 类型的实例 Any 可以表示任意类型,甚至包括方法 (func) 类型 : AnyObject是Any的子集 所有用class关键字定义的对象就是AnyObject 所有不是用class关键字定义的对象就不是AnyObject,而是Any

类型安全

由于 Swift 是类型安全的,所以它会在编译你的代码时进行类型检查(type checks),并把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误。

swift中的 KVC,KVO

那么 KVO 和 KVC 呢?KVO 的魅力在于,您可以在不是自己所创建的类当中使用它,也可以只对您想要监听变化的类使用。KVO 和 KVC 在 Swift 被极大地削弱了。您所观察的对象必须要继承自 NSObject,并且使用一个 Objective-C 类型。您所观察的变量必须要声明为 dynamic。您必须要对想要观察的事务了如指掌。 您可以使用 Rx 或者基于协议来观察对象。但是语言自身是没有原生的解决方案的。

swift中的 runtime, 以及关键字@objc 和dynamic关键字的作用

http://blog.csdn.net/TogeWu/article/details/51151326 动态性最重要的一点就是拿到某个类的方法和属性

1:纯Swift类的函数调用已经不是OC那样的运行时消息了,而是类似C++似得vtable,在编译时就确定了调用那个函数了.

Swift代码中已经没有了Objective-C的运行时消息机制, 在代码编译时即确定了其实际调用的方法. 所以纯粹的Swift类和对象没有办法使用runtime, 更不存在method swizzling. 为了兼容Objective-C, 凡是继承NSObject的类都会保留其动态性, 依然遵循Objective-C的运行时消息机制, 因此可以通过runtime获取其属性和方法, 实现method swizzling.

继承自NSObject的类都遵循runtime, 那么纯粹的Swift类呢? 在属性和方法之前加上@objc关键字, 则一般情况下可以在runtime中使用了. 但有一些情况下, Swift会做静态优化而无法使用runtime. 要想完全使得属性和方法被动态调用, 必须使用dynamic关键字. 而dynamic关键字会隐式地加上@objc来修饰. 获取Swift类的runtime信息的方法, 要加上Swift模块名: id cls = objc_getClass("DemoSwift.MySwiftClass")

加了@objc标识的方法、属性无法保证都会被运行时调用,因为Swift会做静态优化。要想完全被动态调用,必须使用dynamic修饰。使用dynamic修饰将会隐式的加上@objc标识。

To learn a little a day

static和class

class只能用在class类型,但是static在结构体/class/enum都能用。 两者区别:如果用在class类型里面那么static = final class func

swift单利模式

  1. 最简单的单利写法 ``` objc class TestDao: NSObject {

    static let dataCenterObj = ArticleDao() private override init() {}

}

2. 单利2
``` objc
    class var sharedInstance : YYDateAppInfo {
        struct Static {
            static let instance : YYDateAppInfo = YYDateAppInfo()
        }
        return Static.instance
    }

swift归档

Swift实现对象归档时有几个注意点 要继承 NSCoding,实现两个方法 extension 是一个分类,分类不允许有存储能力,所以协议方法不能写在分类中 协议中的init(coder decoder: NSCoder)函数会覆盖原始的构造函数,所以类中至少还要有另一个init方法 如果不指定键名,会使用属性名称作为 key,基本数据类型,需要指定 key class <#className#>: NSObject,NSCoding { // 至少要有一个 init 方法,

swift的闭包循环引用解决方法

  1. 使用weak ``` objc

lazy var printName: ()->() = { [weak self] in if let strongSelf = self { print("The name is (strongSelf.name)") } }

2. 使用unowned
``` objc
// 当闭包和捕获的实例总是互相引用时并且总是同时销毁时,将闭包内的捕获定义为无主引用,当捕获引用有时可能会是  nil  时,则定义为弱引用。弱引用总是可选类型,并且当引用的实例被销毁后,弱引用的值会自动置为  nil  。这使我们可以在闭包内检查它们是否存在
 lazy var asJson:() -> String = {
        [unowned self] in //使用无主引用来解决强引用循环
        if let text = self.jValue {
            return "\(self.name):\(text)"
        }else{
            return "text is nil"
        }
    }

swift自定义打印函数

Xcode中是允许自定义宏定义,这种方式在即使Swift中也是可行的。具体操作如下:

一、设置Swift自定义的宏定义​

1、Target->Build Settings -> Swift Compiler - Custom Flags​

2、添加Debug下的-DDEBUG,添加Release下的-DRELEASE

这样设置后就可以正常的使用#if DEBUG了

swift访问控制

在Swift语言中,访问修饰符有三种,分别为private,internal和public。同时,Swift对于访问权限的控制,不是基于类的,而是基于文件的。其区别如下:

1,private private访问级别所修饰的属性或者方法只能在当前的Swift源文件里可以访问。

2,internal(默认访问级别,internal修饰符可写可不写) internal访问级别所修饰的属性或方法在源代码所在的整个模块都可以访问。 如果是框架或者库代码,则在整个框架内部都可以访问,框架由外部代码所引用时,则不可以访问。 如果是App代码,也是在整个App代码,也是在整个App内部可以访问。

3,public 可以被任何人使用

swift2.0————guard语句和defer语句

  • 1.guard语句

guard语句只会有一个代码块,不像if语句可以if else多个代码块。 那么guard语句的作用到底是什么呢?顾名思义,就是守护。guard语句判断其后的表达式布尔值为false时,才会执行之后代码块里的代码,如果为true,则跳过整个guard语句。

func checkup(person: [String: String!]) {

    // 检查身份证,如果身份证没带,则不能进入考场
    guard let id = person["id"] else {
        print("没有身份证,不能进入考场!")
        return
    }

    // 检查准考证,如果准考证没带,则不能进入考场
    guard let examNumber = person["examNumber"] else {
        print("没有准考证,不能进入考场!")
        return
    }

    // 身份证和准考证齐全,方可进入考场
    print("您的身份证号为:\(id),准考证号为:\(examNumber)。请进入考场!")

}
checkup(["id": "123456"]) // 没有准考证,不能进入考场!
checkup(["examNumber": "654321"]) // 没有身份证,不能进入考场!
checkup(["id": "123456", "examNumber": "654321"]) // 您的身份证号为:123456,准考证号为:654321。请进入考场!
  • 2.defer语句 在一些语言中,有try/finally这样的控制语句,比如Java。这种语句可以让我们在finally代码块中执行必须要执行的代码,不管之前怎样的兴风作浪。在Swift 2.0中,Apple提供了defer关键字,让我们可以实现同样的效果。 ``` objc func writeSomething() {

    let file = OpenFile()

    let ioStatus = fetchIOStatus() guard ioStatus != "error" else {

      return
    

    } file.write()

    closeFile(file)

}


上述示例是一个I/O操作的伪代码,如果获取到的ioStatus正常,那么该方法没有问题,如果ioStatus取到的是error,那么会被guard语句抓到执行return操作,这样的话closeFile(file)就永远都不会执行了,一个严重的Bug就这样产生了。下面我们看看如何用defer来解决这个问题:
``` objc
func writeSomething() {

    let file = OpenFile()
    defer {
        closeFile(file)
    }

    let ioStatus = fetchIOStatus()
    guard ioStatus != "error" else {
        return
    }
    file.write()

}

我们将closeFile(file)放在defer代码块里,这样即使ioStatus为error,在执行return前会先执行defer里的代码,这样就保证了不管发生什么,最后都会将文件关闭。

defer又一个保证我们代码健壮性的特性,我非常喜欢

http://www.cocoachina.com/swift/20150623/12231.html

swift--使用convenience创建便利构造器

首先,重写init方法: 然后,创建便利构造器,注意使用convenience,其中,self.init()就是调用上面init(frame: CGRect)方法,我们在初始化时传一个字符串,并且创建一个label,把这个字符串给label:

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

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

    convenience init(str:String){

        self.init()
        let label = UILabel()
        label.text = str
        label.backgroundColor = UIColor.yellowColor()
        label.frame = CGRectMake(10, 20, 150, 30)
        self.addSubview(label)

    }

下面,就是在自定义UIView中的方法,下面我们开始使用了


        let testView = Test(str:"我是便利构造器")

        testView.backgroundColor = UIColor.redColor()
        testView.frame = CGRectMake(30, 30, 200, 100)
        self.view.addSubview(testView)

swift--标志??的意思

对于不期望某个optional值为nil时func返回nil 或者 因为其值为nil而停止了后续业务的情况下,我们可以用"??"在optionalValue为nil时做赋值保险操作(“??”操作后返回值为非optional)

用法:

newValue = optionalValue ?? value

若optionalValue非nil时,newValue的值为optionalValue的值,若optionalValue为nil时,newValue的值为value的值

func validIntValueForKey(key: String) -> Int { 
  let object = self.objectForKey(key) ?? Int(0)   
//do something
}

SwiftyUserDefaults简单使用

1.先自定义自己的key值

i.e


extension DefaultsKeys {
    static let account          = DefaultsKey<String?>("userName")
    static let password         = DefaultsKey<String?>("password")

}

2.然后使用它,存值

    func save() {
        Defaults[.account]          = self.account
        Defaults[.password]         = self.password
    }

3.取值

    init() {

        self.account                = Defaults[.account]
        self.password               = Defaults[.password]

    }

4.也可以不扩展直接使用

 //        存值:
        Defaults["user"] = "tongxing"
        //        取值:

//        let getUser = Defaults["user"].stringValue
        let getuser1 = DefaultsKey<String?>("user")
        AODlog("\(getuser1)")

        if Defaults.hasKey("user") {

            AODlog("存在")
        }

UserDefault的小补充

使用NSUserDefaults存储自定义的对象

1.先将对象进行归档(NSCoding)

2.然后将对象转换成NSData

//将student类型变为NSData类型
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:student];

3.然后写入NSUserDefaults或者文件

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:student];   

       NSUserDefaults *user = [NSUserDefaults standardUserDefaults];

    NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
    [user setObject:data forKey:@"oneStudent"];

4.读取数据

NSdData *data = [user objectForKey:@"oneStudent"];

 Student *student = [NSKeyedUnarchiver unarchiveObjectWithData:data];

swift的枚举

swift之lazy属性

在swift2.2中,lazy就相当于OC中的懒加载(调用getter方法) 格式:

lazy var 变量: 类型 = { 创建变量代码 }()

本质:i.e.

   // 含义: 当dataList被使用到时, 就会执行等号后面的闭包
    // 所以等号后面的闭包的()是必须写的, 如果不写就会报错
    // 注意点: 如果写懒加载, 那么修饰符必须用var
    lazy var dataList:[String] = {
        print("我被加载了")
        return ["lnj", "lmj", "zs"]
    }()

上面的代码相当于执行了下面的两条语句

 lazy var satatuses: [String] = self.loadStatus()
    func loadStatus() -> [String]
    {
        print("我被加载了")
        return ["lnj", "lmj", "zs"]
    }

swift错误之:

connot convert value of type Int to type CGFloat in coercion

解决方法:

// 先将Int型`titleArr.count`转换为CGFloat型
let tableviewH:CGFloat = CGFloat(titleArr.count)
        tableview = UITableView.init(frame: CGRectMake(50, kScreenHeight - floor(tableviewH) * 50 * 0.5, kScreenWidth - 100, tableviewH * 50))

swift 重写系统属性的setter方法

class StructLevelItem: UIButton {

 // 重写setter方法,去掉高亮
 override var highlighted: Bool {
 get{

 return false
 }
 set{}
 }
}

swift snpkit

left 和leftmargin的区别:假如布局一个view距离屏幕边缘的间距时 left 默认是最左边,leftmargin则会出现系统默认的间距8

监听本地文件状态变化, 比如清理缓存文件,文件大小属性变化

OC : DISPATCH_SOURCE_TYPE_VNODE swift: DispatchSourceFileSystemObject

https://heisenbean.me/2017/06/A-deep-dive-into-Grand-Central-Dispatch-in-Swift/

results matching ""

    No results matching ""