Swift一些概念定义 | 一

一,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);
    }

Leave a Reply

Required fields are marked *