Swift到底是什么?

diuxie

1、var 声明变量,let 声明常量,变量会根据上下文识别类型。

2、溢出操作符——&+,&-,&*,Swift的哲学是触发陷阱比潜在安全漏洞要好

3、字符串支持插值(var)占位符,支持复合赋值操作符+=连接字符串

4、swift必须手动转换类型,不会自动类型转换,譬如int8+int16会报错

5、switch语法与objc差别很大,执行一个分支马上停止,不需要break语句跳出,反而想要穿透到下面分支还要用fallthrough语句。

switch语句每一个分支不能空操作。

Switch既支持一个值与给定值比较,也支持多个值与给定值比较,还支持区间值与给定值比较,多个值用逗号分隔,区间则用三个点…来界定。

switch支持值绑定,在case语句中声明变量或常量,其值绑定为状态码的值。switch绑定值可以配合where语句使用,能额外检查一些条件,这个特性可以创建动态筛选条件。

6、元组——具有逻辑关联的两个或多个值的有限组合,支持索引访问,也可以命名访问,如:

var statusCode

var errorString

let error = (code:statusCode, description:errorString)

元组可以在switch的区间匹配中应用,下划线_可用作通配符,匹配任何值。

7、if-case 语法 为只有一个分支的switch语句提供优雅的替代品。

8、区间既可在switch语句中匹配使用,也可以在for-in循环中使用。

9、通配符_既可以在switch语句使用,也可以在for-in语句中替代迭代器,这样就可以忽略迭代器。

10、for-in循环支持where子句,如 for i in 1…100 where I%3==0 { }

Where子句是用来替代for-in中的if条件判断,使代码看起来更优雅,是可替代的。

11、类型推断——根据上下文推断出实例的类型,不需要显式声明。有些情况下需要明确声明类型,但一般来说,建议尽量利用类型推断。

12、repeat-while替代了do-while

13、导入framework方式如: import Cocoa

不需要#符号,也不需要双引号“”或者尖括号<>

14、字符串双引号前不需要@符号

15、每个字符串都是一个String对象,虽然其本身不是一个集合,但是其底层内容确实以集合的形式存在,字符串的characters属性表示组成这个字符串字符集合。

组成字符串的每个字符也是一个Character对象。

16、\u{}表示Unicode标量,十六进制数放在花括号里。每个字符都有一个或多个Unicode标量构成。一个Unicode标量对应一个基本字符。

多个 Unicode标量构成的字符为组合标量,通常也有有单个标量表示形式,而且其等价。

对于两个字符或者两个字符串,如果它们具有相同的语言学含义和外观,无论是否用相同的Unicode标量创建,都认为两者相等。

标准等价意味着无论用组合标量还是预组合标量,结果都会被当做单个字符。

17、swift不允许直接用索引下标[]来访问字符串中的指定字符,因为swift无法在不遍历前面每个字符的情况下知道指定的索引对应于哪个Unicode标量,该索引必须要先获取到start索引,再通过编译计算到指定索引。

18、swift任何类型都可以用可空类型来说明一个实例可能是nil,而objc-c只允许对象是nil

19、声明实例变量时,在类型后跟随问号?,则表示该变量是可空类型,可以为nil,也可以赋了值。

20、实例变量后跟随感叹号!,其作用是强制展开,无论实例变量是否有值,都会访问封装的值。感叹号!假设有这样一个值,如果没有,这样展开会产生运行时错误。

string实例变量和string!实例变量不是相同的类型——如果你有一个String变量,就无法在不展开可空实例的情况下将String?的值赋予给这个变量。

21、可空实例绑定——如果有值,就将其值赋予一个临时常量或变量,并且使这个常量或变量在条件语句第一个分支代码中可用。其语法与在条件语句中创建常量或变量一致,只是不需要再强制展开可空实例了,这个操作自动完成。

If let Instance = nilInstance, let Instance = nilInstance {}

22、声明实例变量时,在类型后跟随感叹号!,则表示该变量是隐藏式展开可空类型。隐式展开可空类型与普通可空类型重要区别就是不需要展开,使用上不需要if条件语句了。如果这种隐式展开可空类型没有值的话,访问其值会直接导致运行时错误。建议如果某个实例可能为nil,就不要使用隐式展开可空类型。

23、实例后面跟问号?——可空链式调用,与可空实例绑定类似,两者重要区别是,可空链式调用允许把多个查询串联为一个可空实例的值。

24 、感叹号跟在实例后面,其作用就是断言实例不为空,若真为空就崩溃,相当断言效果。

25、nil合并运算符??类似三目操作符?:

那么guard语句的作用到底是什么呢?顾名思义,就是守护。guard语句判断其后的表达式布尔值为false时,才会执行之后代码块里的代码,如果为true,则跳过整个guard语句。guard语句中声明的实例可以在整个方法作用域中使用。

其语法:

guard 布尔表达式 case{ 执行代码 }

——————————————————————————————————————————————————————————

1、swift的Array类型可以持有任何类型的值——对象和非对象都可以。

2、声明数组主要有两种语法,数组实例也支持类型推断

var bucketList:[String]var friends:Array<String>var weeks = ["Monday","Tuesday"] ——字面量语法
var array = Array<String>()
var array = [Int]()

集合Set语法与数组一致

3、声明字典语法,支持类型推断

var dict1:Dictionary<String,Double> = [:]var dict2 = Dictionary<String,Double>()var dict3:[String:Double] = [:]var dict4 = [String:Double]()var dict5 = [“name”:”shelton”,”age”:]
1.
Swift与obj-c的字典区别,就是简化赋值objc用大括号{},swift用中括号[]

4、集合Set是无序,储存元素唯一,数组有序,储存元素可以重复,字典无序,但键值唯一。

5、Swift函数支持嵌套,用元组语法来支持返回多个值,支持变长参数,支持参数带默认值。函数还允许有外部名与内部名。元组也可以作为函数参数

6、闭包就是objc中的Block

闭包语法:

{(参数)->返回类型 in//代码}
1.
闭包可以利用swift的类型推断系统去除参数和返回值的类型信息来简化闭包。

如果闭包代码只有一行表达式,return关键字也可以省略。

闭包甚至可以利用快捷参数名来替代显式声明的参数,做到剔除参数声明来简化闭包。 0表示第一个参数,1表示第二个参数。

尾部闭包语法甚至可以省略掉方法的圆括号。

闭包和函数能记录在其闭合作用域中定义的变量所封装的内部信息。

闭包是引用类型。

func greeting(_ greeting:String) -> (String)->String {
return { (name:String) -> String in
return "(greeting) (name)"
}}

上面函数,有一个String参数,结果返回一个函数,不需要通过嵌入函数来实现,用闭包可以简化之。

7、枚举Enum语法上多了case关键字,支持一系列类型,包括所有的内建数值类型和字符串。在swift中,方法可以和枚举关联,即在枚举中添加方法。

在swift中,枚举是值类型,而值类型的方法不能对self进行修改,如果希望值类型方法能修改self,需要标记这个方法为mutating。

Swift的枚举,除了像其它语言那样定义一些静态的成员值来枚举可能的状态,还提供了一种强大的特性,可以定义带关联值的成员。关联值能让你把数据附在枚举实例上,不同的成员可以有不同类型的关联值。

在枚举中,如果带有递归关联值成员,需要关键字indirect,否则报错。

枚举语法:

enumname.enumvalue. 或者 .enumvalue

8、创建项目中,入口文件main.swift没有main游戏函数

在main.swift 创建其它文件的结构或类,不需要import对应文件

9、结构体Struct也是可以声明自己的方法,但是若方法要修改结构体的属性,需要用关键字mutating标志,因为结构体和枚举都是值类型。

10、类与结构体的区别之一,支持继承,在重载父类方法的时候要添加override关键字

Swift的类有个新特性,可以禁止子类重载某个函数,在该函数增加final关键字。如果我们在声明一个类时,在class前加上final修饰符,则表示禁止类被继承。

11、结构体和类都支持类方法(c++的静态方法),但是结构体需要在方法前用static标记,而类则用class标记该方法。用class标记的类方法可以由子类重载,想要子类不能重载,则需要用static标记。也就是类和结构体都支持static关键字标记类方法,但该方法不支持重载。当然也可以用final class来标记类方法。

12、属性分存储属性和计算属性。

存储属性用来存储数据,可以是只读属性,也可以是读写属性,只读属性用let声明。

swift增加一个惰性存储属性概念,用lazy关键字修饰,惰性储存属性的值只在第一次访问的时候才会出现,因为它依赖类型的外部因素,必须要满足某些前提条件才能计算得到。注意,标记为lazy的属性只会被计算一次。

只读的计算属性用var来定义,与只读得存储属性不同。计算属性的类型必须显式声明

针对objc的kvo,swift提供一种特性——属性观察,但计算属性不能用。

13、与类方法类似,有类属性,用class标记的属性子类可以重载自定义,用static标记的子类不可以重载修改。枚举,结构体和类都支持类属性。

类计算属性与类方法很类似,区别是一个用关键字var,另一个用func,类计算属性没有圆括号。

计算属性如果没有写入方法,可以省略定义中的get。

子类要重载类计算属性,同样要标记override。

14、swift提供了 open、public、internal、fileprivate、private五层访问控制。objc没有这些访问限制。

private:访问级别所修饰的属性或者方法只能在当前类里访问.(注意:Swift4 中,extension 里也可以访问 private 的属性。)

fileprivate:访问级别所修饰的属性或者方法在当前的 Swift 源文件里可以访问。

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

public: 可以被任何人访问。但其他 module 中不可以被 override 和继承,而在 module 内可以被 override 和继承。

open: 可以被任何人使用,包括 override 和继承。

15、swift中的初始化方法意义和c++的构造函数类似。与普通方法类似,但是没有func关键字标记,也没有返回值,用init关键字做方法名,参数个数可变。

结构体提供了一种默认的初始化方法,会将所有属性都作为参数。与结构体不同,类没有默认的成员初始化方法。

在方法实现中,属性如果遇到同名参数才需要指定self,不然则不需要。

在初始化方法中允许给常量赋值,其它方法则不允许。

16、初始化增加了两个概念:指定初始化和便捷初始化,便捷初始化需要在init前加上关键字convenience。还有一个required关键字不能忽略,表示子类必须重载该指定初始化方法,只是不用override关键字,而是用required关键字。便捷初始化参数可以灵活不需包含所有属性,且内部必须要调用到一个指定初始化方法。

在创建Swift对象,可以类似:var obj = classname.init(), 也可以类似:var obj = classname(),括号里的参数与init实现一致。

17、反初始化就是c++中的析构函数思想,也相当于objc的www.sangpi.comdealloc,在实例被清除出内存钱会调用到。

18、初始化还有个概念可失败初始化,其实就是可空实例关联的东西,其语法需要再init后跟随一个问号,也可以跟随一个感叹号。感叹号表示返回隐式展开可空类型实例,其使用起来方便(不需要写可空类型展开的语法),但不如跟随问号安全。

19、在被赋给另一个实例或是作为参数传递给函数时,值类型总是被复制。

String,Int, Array, Dictionary等是Struct,是值类型。

Class是引用类型。

声明为常量的值类型不能改变属性,即使属性在类型实现中是用var声明也一样。但是声明为常量的引用类型实例的属性却可以被修改。

建议不要在值类型内使用引用类型,确实需要再结构体内使用引用类型,最好使用不可变的实例。

我们预期,当把值类型实例赋给新变量、常量或传递给函数时,实例会被复制。但是,若值类型内有引用类型,副本实例和原来实例中引用类型实例还是指向同一个实例,改变这个引用实例,副本实例中的引用实例也会被影响。

值类型内的引用类型属性在复制时只是浅拷贝,并不会创建新的实例,而是指向同一个实例。

20、理解相等与同一的概念,相等通常是指俩实例的内容相等,同一是指俩实例指向内存中同一个实例。基本数据类型String、Int、Double、Float、Array、Dictionary都可以检查相等性。新增语法===来检测俩实例的同一性,但值类型不能用同一性检查。类实例若要判断相等性==,则需要实现协议Equatable。

21、关于值类型的复制行为,swift语言提供了一种写时复制的特性。在某个实例需要修改或写入存储时,该实例才会产生一份自己的副本,在这之前,它们会维护自己对同一份存储的引用。

因此我们在赋值或将实例作为参数传递时,在它们没被修改或写入存储时,它们还是对同一份存储进行引用。这样值类型就可以避免创建多余的数据副本。

阅读 247
1 声望
1 粉丝
0 条评论
你知道吗?

1 声望
1 粉丝
文章目录
宣传栏