一,Swift中的类型有Class,enum,struct;其中Class是引用类型,其他两种是值类型。
二,引用类型的引用计数:
引用计数只是针对类的实例,没有结构体和枚举。结构体和枚举是值类型,不是引用类型,没有通过引用存储和传递。
闭包也属于引用类型;
三,循环引用:
weak,弱引用,类似于OC中的weak,当指向的对象被释放后,weak指针置为nil;
unowned,无主引用,类似于OC中的__unsafe_unretained,对象释放后,unowned指针不会置为nil,下次去发送消息会崩溃;
[unowned self] in , [weak self] in解决闭包中的循环引用问题;
详细:
https://www.cnswift.org/automatic-reference-counting
例子: //闭包 lazy var asHtml : () -> String = { [weak self] in print("xxxx") //这里调用了self,asHtml也属于self,造成了循环引用,所以得[weak self] in, return self.debugDescription }
四,lazy关键字类似于懒加载的作用;可修饰方法变量和属性变量,如果修饰方法,则方法内可以用self.去调用当前类中的变量。
//例子-1 lazy var userCenterListV : SKBaseTableView = { let userCenterListV = SKBaseTableView(frame: .zero, style: .grouped); userCenterListV.delegate = listDelegate; userCenterListV.dataSource = listDelegate; return userCenterListV; }(); //例子-2 lazy var names: NSArray = { let names = NSArray() print("只在首次访问输出") return names }()
例如以下代码,解释lazy闭包的具体执行:
lazy var iconImagView: UIImageView = { () -> UIImageView in let iconImagView = UIImageView.init(); return iconImagView; }()
定义了一个变量iconImagView,然后通过闭包返回一个UIImageView类型的实体,赋值给iconImagView,所以{ }为函数体,( )等于执行力函数,所以可以简写为,去掉参数和返回值:
lazy var iconImagView: UIImageView = { let iconImagView = UIImageView.init(); return iconImagView; }()
上边两种变量的初始化等价于:
lazy var iconImagView = tmpImageView(); func tmpImageView() -> UIImageView{ let iconImagView = UIImageView.init(); return iconImagView; }
五,Swift访问级别关键字:
open , public , internal , fileprivate ,或 private 修饰符来定义访问级别。
默认为:internal
一个方法中,如果有参数是私有的,那么这个函数的定义必须得是私有的,否则编译会报错,例如:
//其中,SomeInternalClass传递过来的是一个私有属性 private func someFunction() -> (SomeInternalClass, SomePrivateClass) { // function implementation goes here }
枚举中的独立成员自动使用该枚举类型的访问级别。例如一下枚举的类型是public,那么其中里边的成员也是public级别了。
创建子类时的访问级别不能高于父类的访问级别。
public enum CompassPoint { case north case south case east case west }
属性的getter和setter方法进行级别设置:
private(set) var numberOfEdits = 0//说明只读,外部不能修改
private(get) var numberOfEdits = 0//只写,外部不能访问
public private(set) var numberOfEdits = 0,两种修饰,public修饰get级别,private修饰set级别。
六,自定义一个坐标加/减法。
struct Vector2D { var x = 0.0, y = 0.0 } extension Vector2D { static func + (left: Vector2D, right: Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x, y: left.y + right.y) } } // extension Vector2D { static prefix func - (vector: Vector2D) -> Vector2D { return Vector2D(x: -vector.x, y: -vector.y) } }
七,遵循Equatable协议的直接可以进行比较
Swift 为以下自定义类型提等价运算符供合成实现:
1,只拥有遵循 Equatable 协议存储属性的结构体;
2,只拥有遵循 Equatable 协议关联类型的枚举;
3,没有关联类型的枚举。例如:
struct Strt_2D: Equatable { var x = 0.0,y = 0.0; } // let fir2D : Strt_2D = Strt_2D(x: 2.0, y: 3.0); let sec2D : Strt_2D = Strt_2D(x: 1.0, y: 3.0); if fir2D == sec2D{ print("相等") }else{ print("不相等") } //输出不相等
自定义运算符:
prefix operator +++ {} static prefix func +++ (vector: inout Vector2D) -> Vector2D { vector += vector return vector }
infix operator +- { associativity left precedence 140 } //优先级
八,关键字is判断当前实例是否属于一个特定的类,返回bool,is是类型检查操作符,只能对其类的实例进行操作判断。
as,将某个实例转换成其对应的类型;
as直接进行转换;
as!,强制转换,如果类型不符,那么运行也会错误;
as?,可选转换,如果类型不符,转换返回nil;
let selfObj = self as SKBaseViewController; selfObj.test = "asdkjadsjjladsl"; //其实就是类似于OC里边的转换 (UIVLabel *)self.view;
Anyobject和Any类似于OC中的id类型,不确定具体的实例类型。
Anyobject可以表示class类型的实例;
Any可表示class,枚举,结构体类型的实例;
where关键字,类似于mysql中的约束条件,增加约束,例如:
case let someDouble as Double where someDouble > 0:
nil,nil只能赋值给一个非可选的常亮或者变量,也就是如果不是?修饰的,那么则不能赋值为nil,同理,如果?修饰的变量或者常量,在定义的时候,系统会初始化其值为nil。
九,? ! 缺省值和展开;
?,告诉系统,当前变量可以被赋值为nil,swift中,如果创建的变量不被初始化,则会报错,那么需要用到缺省符号?,作用是系统会自动将一个变量在定义的时候赋值为nil,然后将其作为一个可选值,也就是说,当前被?修饰的变量,可以不用进行初始化,也不会报错。那么需要用到可选值的时候,需要进行展开。
缺省值也能调用自己的属性方法等,缺省变量的属性也是缺省值,例如:
let vars : String? vars = "阔以啊。"; print(vars?.utf8CString); //输出,Optional代表可选 Optional(ContiguousArray([-23, -104, -108, -28, -69, -91, -27, -107, -118, -29, -128, -126, 0]))
可选值的展开!:
1,!符号直接进行强制展开,可通过if判断,然后进行展开,否则如果! 后值为nil,为会崩溃。
//用!进行了强制展开 let vars : String? vars = "阔以啊。"; if(vars != nil){ print(vars!); }
对缺省值的属性进行强制展开:
print((vars?.utf8CString)!);
2,直接通过if赋值进行展开,不需要!,这里的if进行了3步操作,首先=进行赋值,然后判断新变量是否为空,如果不为空则!,也就是进行了展开,例如:
let vars : String? vars = "阔以啊。"; if let var_ss = vars{ print("this is non optional var",var_ss); }else{ print("...."); } //输出: this is non optional var 阔以啊。
3,通过guard关键字进行判断,类似于if,if是满足条件执行,guard不满足条件执行,例如:
var vars : String? = nil; vars = "你好"; //这里如果不满足条件才会执行 guard nil != vars else { print("no empty"); return; } //以下就可以全部进行强制转换,不怕为nil print(vars!);
十,便利初始化器。
convenience init(_ groupedFrame:CGRect) { self.init(frame: groupedFrame,style: .grouped); }
十一,告知用户一些message,例如当前方法太久,已经有新方法代替他的时候。
@available(iOS, introduced: 2.0, deprecated: 13.0, message: "Use -[UIDevice userInterfaceIdiom] directly.") public func UI_USER_INTERFACE_IDIOM() -> UIUserInterfaceIdiom
十二,闭包,类似于OC Block。
//创建一个函数,传递一闭包参数 func bibao(task: () -> String) -> Void { print(task());//执行了输出闭包,所以可以断言闭包是有返回值的。 } //闭包参数的参数为空,返回值为String。 执行bibao()函数 var block : () -> String = { return "我的名字"; } //执行 bibao(task: block);直接将block闭包传给了bibao方法。 这里是自己定义了一个需要的闭包类型,如果直接传入: bibao(task: { () -> String in return "你好啊啊啊"; }) //直接传入了,它的形式为: { (parameters) -> (return type) in statements } //闭包的函数整体部分由关键字 in 导入,这个关键字表示闭包的形式参数类型和返回类型定义已经完成,并且闭包的函数体即将开始。
2,委托初始化器,一个init方法调用(委托)另外一个init进行初始化,此初始化方法为委托初始化器。
以下定义了5个初始化方法,一个类方法。
第一个初始化方法是重写了父类的初始化方法;
第二个,第三个是自生的init方法,调用了父类的init方法。
第四个系统的,第五个是便捷初始化器,一个类里边可以写多个便捷初始化器,需形参名不同。
override init(frame: CGRect, style: UITableView.Style){ super.init(frame: frame, style: style); if #available(iOS 11.0, *){ self.contentInsetAdjustmentBehavior = .never; self.estimatedSectionHeaderHeight = 0; self.estimatedSectionFooterHeight = 0; } } init(groupframe: CGRect) { super.init(frame: groupframe, style: .grouped); } init(plainFrame: CGRect) { super.init(frame: plainFrame, style: .plain); } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } convenience init(_ groupedFrame:CGRect) { self.init(frame: groupedFrame,style: .grouped); } static func initPlain(frame: CGRect) -> SKBaseTableView{ let plainList = SKBaseTableView.init(frame: frame, style: .plain); return plainList; }
convenience init(groupframe: CGRect) { self.init(frame: groupframe, style: .grouped); } convenience init(plainFrame: CGRect) { self.init(frame: plainFrame, style: .plain); } convenience init(_ groupedFrame:CGRect) { self.init(frame: groupedFrame,style: .grouped); }