swift学习笔记-OC与swift区别,从OC到swift你可以看看这个

创建对象

OC:alloc initWith

Swift:(XXX:)

调用方法

OC:[uicolor redcolor]

Swift:uicolor.redcolor()

枚举

OC:UIButtonTypeContactAdd

Swift:UIButtonType.ContactAdd

输出

OC:NSLog(@"Hello, World!");

Swift:2.0开始:  print("Hello, World!")

注释

* Swift的编译器将会在编译代码时自动忽略掉注释部分

*单行注释//

*多行注释/**/

与C语言多行注释不同,Swift的多行注释可以嵌套在其它的多行注释之中嵌套多行注释

*注释嵌套/*/**/*/

常量变量

* let常量:常量的值一旦设定就不能改变

* var变量:变量的值可以随意更改

*常量&变量的使用原则:

*为保证数据的安全性尽量先用let,只有需要改变的时候才使用var

常量定义格式

*声明符号常量名称:类型标注

* let number: Int

*特点:一旦设定就不能改变

定义变量格式

*声明符号常量名称:类型标注

* var number: Int

*特点:变量的值可以随意更改

*注意:一般来说你很少需要写类型标注。如果你在声明常量或者变量的时候赋了一个初始值,Swift可以推断出这个常量或者变量的类型

常量和变量的命名

*你可以用任何你喜欢的字符作为常量和变量名,包括Unicode字符

*常量与变量名不能包含数学符号,箭头,保留的(或者非法的)Unicode码位,连线与制表符

*也不能以数字开头,但是可以在常量与变量名的其他地方包含数字

* ...和C和OC一样, no zuo no die

注意:

*如果你需要使用与Swift保留关键字相同的名称作为常量或者变量名,你可以使用反引号(`)将关键字包围的方式将其作为名字使用。

*无论如何,你应当避免使用关键字作为常量或变量名,除非你别无选择。

let🐶= "狗"

let `int` = 88

类型推断

*编译器可以在编译代码的时候自动推断出表达式的类型。(其它语言是没有类型推断)

*原理很简单,只要检查你赋的值即可

*如果没有指定表达式的类型,也没有赋予初始值,编译器会报错(type annotation missing in pattern)

//:指定类型

let dValue: Double

dValue = 22.2

print(dValue)

//:不指定类型,利用类型推断

let num = 10

print(num)

let value = 10.10

print(value)

元祖

*元组(tuples)把多个值组合成一个复合值

*将多个相同或者不同类型的值用一个小括号括起来就是一个元祖

*元组内的值可以是任意类型,并不要求是相同类型

*作为函数返回值时,元组非常有用

注意:

*元组在临时组织值的时候很有用,但是并不适合创建复杂的数据结构。如果你的数据结构并不是临时使用,请使用类或者结构体而不是元组

//定义元祖

let student = ("lnj", 30, 99.8)

//通过下标来访问元组中的单个元素

print(student)

print(student.0)

print(student.1)

print(student.2)

//给单个元素命名

let student1 = (name:"lnj",age:30,score:99.8)

print(student1.name)

print(student1.age)

print(student1.score)

//元组的内容分解(decompose)

let (name , age , score) =  ("lnj", 30, 99.8)

print(name)

print(age)

print(score)

类型安全

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

* swift对数据类型要求异常严格, swift中任何时候,都不会做`隐式转换`,如果要对不同类型的数据进行计算,必须显示类型转换

注意:

*结合数字类常量和变量不同于结合数字类字面量。字面量8可以直接和字面量3.1415926相加,因为数字字面量本身没有明确的类型。它们的类型只在编译器需要求值的时候被推测

* Double和CGFloat也需要转换

let ii = 10

let jj = 10.1

//let sum = ii + jj //错误写法

let sum = Double(ii) + jj

print(sum)

//注意:Double()并不会修改intValue的值,而是通过intValue的值生成一个临时的值赋值给doubleValue

print(ii)

// Double和CGFloat也需要转换

let size = CGSize(width: 10, height: 10)

let res = size.width + CGFloat(dValue)

流程控制结构

Swift提供了类似C语言的流程控制结构(if/switch/for/while/dowhile)

分支if

*只能以Bool作为条件语句

*条件语句不需要加()

* {}不能省略

* Swift中if分支的模式可以使用where语句来判断额外的条件

*其它和OCif一样

let intValue = 10

if intValue > 5{

print("OK")

}

let testValue: Int? = 10

if let d = testValue where testValue > 9

{

print("满足")

}

Bool类型

* C语言和OC并没有真正的Bool类型

* OC语言的Bool类型YES/NO是`typedef signed char BOOL;`非0即真

Swift引入了真正的Bool类型true/false

* Swift中没有C和OC中非零即真的概念

* Swfit中逻辑值只有两个true/false

*如果你在需要使用Bool类型的地方使用了非布尔值,Swift的类型安全机制会报错

//if intValue = 10 { //可能将判断写错, Swift有效的避免了这种情况

if intValue == 10 {

print(intValue)

}

三目运算符

*三目运算符的特殊在于它是有三个操作数的运算符,它简洁地表达根据问题成立与否作出二选一的操作

*格式:问题?答案1 :答案2

提示:

* Swift中三目运算符用得很多

注意:

*过度使用三目运算符会使简洁的代码变的难懂。我们应避免在一个组合语句中使用多个三目运算符

let result = intValue > 20 ? 20 : 10

分支Switch

* OC中case后面必须加上break否则会贯穿, Swift不用

* Swift中如果想贯穿必须使用fallthrough

* OC中可以不写default,Swift中只有满足所有条件才能忽略default

* OC中default位置可以随便放,Swift不可以

* OC中在case中定义变量需要加大括号,否则作用域混乱, Swift不用加大括号

* Swift中的switch可以判断区间和元祖

* Swift中case分支的模式可以使用where语句来判断额外的条件

注意:

Swift中每一个case分支都必须包含至少一条语句,不像C语言里的switch语句,在Swift中,switch语句不会同时匹配多个条件

var rank = "A"

switch rank{

//default:

//    print("没有评级")

case "A", "B":

var num = 10

print("优")

fallthrough

case "C":

print("差")

default:

print("没有评级")

}

匹配区间

*闭区间操作符...包含头包含尾

*半开区间操作符..<包含头不包含尾

var age1 = 10

switch age1 {

case 0:

print("0")

case 1..<18:

print("未成年")

case 18..<30:

print("成年")

default:

print("老年人")

}

//:匹配元祖

var point = (50, 50)

switch point{

//只有where后面的条件表达式为真才赋值并执行case后的语句

case (0, 0):

print("原点")

case (50, 50):

print("中点")

default:

print("Other")

}

//:值绑定(Value Bindings)

switch point{

//只有where后面的条件表达式为真才赋值并执行case后的语句

case var(x, y) where x > y:

print("\(x) > \(y)")

case var(x, y) where x < y:

print("\(x) < \(y)")

default:

print("Other")

}

可选类型

*可选类型表示变量可以有值,也可以没有值

* C和Objective-C中并没有可选类型这个概念

* Swift中只有可选类型才可以赋值为nil

*如果你声明一个可选常量或者变量但是没有赋值,它们会自动被设置为nil

*格式: Optional<类型>或在类型后面加上?号

可选类型的取值是一个枚举

* None没有值

* Some有值

*由于可选类型在Swift中随处可见,所以系统做了一个语法糖,在类型后面加上?

注意:

* nil不能用于非可选的常量和变量。如果你的代码中有常量或者变量需要处理值缺失的情况,请把它们声明成对应的可选类型。

* Swift的nil和Objective-C中的nil并不一样。在Objective-C中,nil是一个指向不存在对象的指针,所以Objective-C只有对象类型才能被设置为nil(基本类型不行)。在Swift中,nil不是指针——它是一个确定的值,用来表示值缺失。任何类型的可选状态都可以被设置为nil,不只是对象类型。

var doubleValue1: Optional = 10.10

var intValue1: Int? = 0

intValue1 = nil

强制解析(forced unwrapping)

let url = NSURL(string: "http://www.520it.com/")

//如果强制解析OptionalValue,但是OptionalValue中没有值时会引发一个运行时错误

print(url!)

//需要考虑url是否有值

if url != nil{

let request = NSURLRequest(URL: url!)

}

可选绑定(optional binding)

*不需要考虑url是否有值,能进入{}一定有值

*不仅可以用来判断可选类型中是否有值,同时可以将可选类型中的值赋给一个常量或者变量

*可选绑定可以用在if和while语句中

提示:

*在实际开发中,使用频率很高

if let url3 = NSURL(string: "http://www.520it.com/"){

let request = NSURLRequest(URL: url3)

}

隐式解析可选类型(implicitly unwrapped optionals)

*有时候在程序架构中,第一次被赋值之后,可以确定一个可选类型_总会_有值。在这种情况下,每次都要判断和解析可选值是非常低效的,因为可以确定它总会有值

*隐式解析可选类型,并不需要每次都使用解析来获取可选值,一个隐式解析可选类型其实就是一个普通类型,但是可以被当做非可选类型来使用

*格式:将可选类型后面的?改为!

* let xmgButton: UIButton!

注意:

*如果一个变量之后可能变成nil的话请不要使用隐式解析可选类型。如果你需要在变量的生命周期中判断是否是nil的话,请使用普通可选类型

let url3: NSURL? = NSURL(string: "http://www.520it.com/")

let url4: NSURL! = NSURL(string: "http://www.520it.com/")

print(url3!) //需要惊叹号来获取值

print(url4)  //不需要感叹号

循环

for循环-传统

* for后的圆括号可以省略

*只能以bool作为条件语句

*如果只有条指令for后面的大括号`不可以`省略

* for后面的三个参数都可以省略,如果省略循环保持语句,那么默认为真

for var i = 0; i < 10; i += 1

{

print(i)

}

for循环-Swift

*闭区间:包含区间内所有值a...b例如: 1...5

*半闭区间:包含头不包含尾a..

//  0~9之间

for i in 0..<10

{

print(i)

}

// 0~10

for i in 0...10

{

print(i)

}

忽略_

*不关心下标可以使用_忽略下标

*在Swift中_使用非常广泛

for _ in 0...10

{

print("lnj")

}

while循环

//: while循环,每次在循环开始时计算条件是否符合

var n = 0

while n < 10

{

print(n)

n += 1

}

//: repeat-while,每次在循环结束时计算条件是否符合

var m = 0

repeat{

print(m)

m += 1

}while m < 10

数组(有序数据集)

* Swift的Array类型被桥接到Foundation的NSArray类。

*格式: [] / [Int]() / Array()

* let不可变数组

* var可变数组

注意:

*不需要改变集合的时候创建不可变集合是很好的实践。如此Swift编译器可以优化我们创建的集合。

//创建一个空数组

var arrayM5: [String] = []

var arrayM4 = [String]()

var arrayM6 = Array()

//创建一个带有默认值的数组

let array1 = ["lnj", "lmj"]

let array2 = Array(count: 5, repeatedValue: 0)

//遍历

for item in array1{

print(item)

}

//遍历同时拿到索引

for (index, item) in array1.enumerate()

{

print("index = \(index), item \(item)")

}

//获取元素

array1[0]

array1[1]

//添加元素

//不能像不可变数组中添加内容

//array1.append("why")

// let不可变对象, var可变对象

var arrayM = ["lnj", "lmj"]

arrayM.append("why")

//数组可以存放任意类型

var arrayM2 = ["lnj", "lmj", 123]

arrayM2.append("456")

//如果需要添加其它类型必须提前声明为AnyObject

//arrayM.append(123)

//合并数组

var arrayM3 = ["zs", "ls", "ww", "zl"]

arrayM += arrayM3

//只有相同类型的数组才可以合并

//arrayM2 += arrayM3

print(arrayM.count)

//和区间搭配使用

arrayM += arrayM3[0...2]

print(arrayM.count)

//删除

arrayM3.removeAtIndex(1)

arrayM3

//删除所有

//arrayM3.removeAll()

//和区间搭配使用

//arrayM3.removeRange(Range(start: 0, end: 2))

arrayM3.removeRange(0..<2) //其实Range就是半闭区间

arrayM3

//删除并保留容量

arrayM3.removeAll(keepCapacity: true)

arrayM3.capacity

arrayM3.append("1")

arrayM3.capacity

arrayM3.append("2")

arrayM3.capacity

arrayM3.append("3")

arrayM3.capacity

arrayM3.append("4")

arrayM3.capacity

arrayM3.append("5")

//超过容量,容量会直接*2

arrayM3.capacity

字典(无序数据集)

* Swift的Dictionary类型被桥接到Foundation的NSDictionary类。

*格式[:] / Dictionary

* let不可变字典

* var可变字典

注意:

*一个字典的Key类型必须遵循Hashable协议

//创建一个空字典

var dict3: [String: AnyObject]

dict3 = [:]

var dict4 = [String: AnyObject]()

//创建一个带有默认值字典

var dict5 = ["name": "lnj", "age": 30]

//最常见的字典类型[String : AnyObject],例如JSON

var dict = ["name":"lnj", "age": 30]

//遍历字典

// k,v可以随便写,前面是key后面是value

for (k, v) in dict{

print(k)

print(v)

}

//获取元素

dict["name"]

//添加元素

//如果key不存在会新增

dict["gender"] = "man"

dict

//替换元素

//如果key存在会替换

dict["name"] = "why"

//删除元素

dict.removeValueForKey("name")

dict

//合并字典

var dict2 = ["score": 123]

for (k, v) in dict2{

dict[k] = v

}

dict

字符串

* Swift的String类型与Foundation NSString类进行了无缝桥接

* OC语言中的字符串也是以\0结尾, Swift不是

* OC中字符串是一个对象, Swift中使用String是一个结构体,效率更高,支持遍历

注意

* Swift的String类型是值类型。如果您创建了一个新的字符串,那么当其进行常量、变量赋值操作,或在函数/方法中传递时,会进行值拷贝。任何情况下,都会对已有字符串值创建新副本,并对该新副本进行传递或赋值操作

// Swift字符串不是以\0结尾

var stringValue = "abc\0bcd"

print(stringValue)

//遍历字符串

var str = "南哥很帅"

for c in str.characters

{

print(c)

}

//连接字符串和字符

var str2 = "cool"

str2 += str

let myAge:Int? = 30

let myName = "lnj"

//字符串插值

//拼接字符串的时如果字符串是可选内心,要特别注意,会带上Optional

let str3 = "name = \(myName), age = \(myAge!)"

//需要格式的时候,怎么办00:00:00

let frmStr = String(format: "%02d:%02d:%02d", arguments: [9, 23, 8])

//字符串截取,建议使用NSString

let str4 = "xmgcool"

let nsStr: NSString = str4

let subStr = nsStr.substringWithRange(NSMakeRange(0, 3))

//使用startIndex属性可以获取一个String的第一个Character的索引

//使用endIndex属性可以获取最后一个Character的后一个位置的索引

let subStr2 = str4.substringToIndex(str4.startIndex.advancedBy(3))

let range = Range(start: str4.startIndex, end: str4.startIndex.advancedBy(3))

let subStr3 = str4.substringWithRange(range)

函数:

*函数是用来完成特定任务的独立的代码块。你给一个函数起一个合适的名字,用来标识函数做什么,并且当函数需要执行的时候,这个名字会被用于“调用”函数

*格式:

* func函数名称(参数名:参数类型,参数名:参数类型...) ->函数返回值{函数实现部分}

没有参数没有返回值

1.可以写为->Void

2.可以写为->()

3.可以省略

* Void。它其实是一个空的元组(tuple),没有任何元素,可以写成()

func say() -> Void{

print("lnj")

}

say()

func say2() -> (){

print("lnj")

}

say2()

func say3(){

print("lnj")

}

say3()

有参数没有返回值

内部/外部参数

*内部参数: Swift2.0以前,默认情况下的参数都是内部参数

*          Swift2.0开始,默认将第二个参数名称作为外部参数

*外部参数只能外部用,函数内部不能使用,函数内部只能使用内部参数

*忽略外部参数:在内部参数前加_

func sum(a: Int, b: Int){

print(a + b)

}

sum(10, b: 20)

func summ(a: Int, _ b: Int){

print(a + b)

}

summ(10, 20)

// xy外部参数, ab内部参数

// Swift2.0以前可以写#

func sum2(x a: Int, y b: Int){

print(a + b)

}

sum2(x: 10, y: 20)

默认参数(Default Parameter Values)

*格式: func method(parameter: Int = 0){}

*当默认值被定义后,调用这个函数时可以忽略这个参数

*其它语言的默认参数必须写在最后面, Swift可以写在任意位置

注意

*将带有默认值的参数放在函数参数列表的最后。这样可以保证在函数调用时,非默认参数的顺序是一致的,同时使得相同的函数在不同情况下调用时显得更为清晰。

func joinString(s1:String , jioner:String = "❤️",toString s2:String) ->String

{

return s1 + jioner + s2;

}

joinString("lnj", jioner: "和", toString: "xmg")

joinString("lnj", toString: "xmg")

常量参数和变量参数(Constant and Variable Parameters)

*函数参数默认是常量,在函数内部不能修改

*如果想在函数中修改参数,必须在参数前加上var

注意

*对变量参数所进行的修改在函数调用结束后便消失了,并且对于函数体外是不可见的。变量参数仅仅存在于函数调用的生命周期中

func swap(var a:Int, var b:Int)

{

print("交换前a = \(a) b = \(b)")

let temp = a;

a = b;  //可以修改,但不会影响实参

b = temp;

print("交换后a = \(a) b = \(b)")

}

var x = 10

var y = 20

print("交换前a = \(x) b = \(y)")

swap(x, b: y)

print("交换后a = \(x) b = \(y)")

输入输出参数(In-Out Parameters)

*变量参数,正如上面所述,仅仅能在函数体内被更改。如果你想要一个函数可以修改参数的值,并且想要在这些修改在函数调用结束后仍然存在,那么就应该把这个参数定义为输入输出参数(In-Out Parameters)

*定义一个输入输出参数时,在参数定义前加inout关键字

注意

*输入输出参数不能有默认值,而且可变参数不能用inout标记。如果你用inout标记一个参数,这个参数不能被var或者let标记。

func swap2(inout a:Int, inout b:Int)

{

let temp = a;

a = b;

b = temp;

}

var x1 = 10;

var y1 = 20;

print("交换前a = \(x1) b = \(y1)")

swap2(&x1, b: &y1)

print("交换后a = \(x1) b = \(y1)")

可变参数(Variadic Parameters)

*一个可变参数可以接收零个或多个值

*如果没有变参函数,并且函数的参数个数又不确定那么只能写多个方法或者用将函数参数改为集合

*格式func method(parameter: Int...){}

*可变参数在函数中可以当做一个数组

注意

*一个函数最多只能有一个可变参数

*变参只能是同种类型的数据

*变参必须指定数据类型

*如果函数有一个或多个带默认值的参数,而且还有一个可变参数,那么把可变参数放在参数表的最后

func add(nums:Int..., other:Int) -> Int

{

var sum = 0;

for num in nums

{

sum += num

}

return sum + other

}

print(add(1, 2, 3, other: 9))//会将99传递给第一个参数,后面的传递给nums

//没有参数有返回值

func getNumer() ->Int{

return 998

}

print(getNumer())

//有参数有返回值

func sum3(a: Int, b: Int) ->Int{

return a + b

}

print(sum3(10, b: 20))

//嵌套函数

func showArray(array:[Int])

{

//嵌套函数

func printArray(arr:[Int])

{

for number in array

{

print("\(number), ")

}

}

printArray(array)

}

showArray([1, 3, 5, 7, 9])

函数类型(Function Types)

*函数类型作为参数类型(Function Types as Parameter Types)

*函数类型作为返回类型(Function Types as Return Types)

*嵌套函数(Nested Functions)

提前退出

*像if语句一样,guard的执行取决于一个表达式的布尔值。我们可以使用guard语句来要求条件必须为真时,以执行guard语句后的代码。

*如果guard语句的条件被满足,则在保护语句的封闭大括号结束后继续执行代码

*任何使用了可选绑定作为条件的一部分并被分配了值的变量或常量对于剩下的保护语句出现的代码段是可用的

*如果条件不被满足,在else分支上的代码就会被执行。

* else这个分支必须转移控制以退出guard语句出现的代码段。它可以用控制转移语句如return,break,continue或者throw做这件事

func divide3(dividend: Double?, divisor: Double?) -> Double? {

guard let dividend = dividend else {

return .None

}

guard let divisor = divisor else {

return .None

}

guard divisor != 0 else {

return .None

}

return dividend / divisor

}

print(divide3(10, divisor: 20))

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容