Swift与OC的不同点

  • 导入框架的方式

    • OC使用#import <UIKit/UIKit.h>
    • Swift使用import UIKit
  • 定义标识符的方式
    • Swift中定义标识符,必须指定该标识符是一个常量还是一个变量
  • 语句结束后的标志
    • Swift可以不用分号";"分割(只限于一行有一条语句时)
    • OC需要分号进行分割
  • 打印语句
    • 直接使用print()语句进行打印
    • OC中使用NSLog()语句进行打印

常量和变量的使用注意

  • 优先使用常量
  • 常量的本质:保存的时常量的内存地址,不可以修改,但可以通过内存地址拿到对象内部属性进行修改

Swift中的类型推导

在定义一个标识符,如果有直接赋值,那么会根据赋值的类型推导出前面标识符的类型,所以后面的类型可以省略

Swift中没有隐式转换,所以只有相同类型之间才可以进行运算

显式类型转换:Int(),Double()等

逻辑分支

if条件判断可以不要括号,没有非0即真的概念

  • OC中BOOL的值为YES/NO
  • Swift中的布尔Bool类型的值为true/false

guard的使用,适合多层if嵌套,使用guard代替,该语法是自Swift 2.0以后推出的.作用和if相同,但是可读性比if好.

switch的用法:

  • switch可以不跟()
  • case语句结束后,不跟break,系统会默认添加
  • 如果希望一个case中出现case穿透,可以在case语句结束后跟上fallthrough
  • case后面可以跟多个条件,多个条件以","分割
  • switch可以判断浮点型
  • switch可以判断字符串
  • switch可以判断区间

swift中的区间表示:

  • a..<b 相当于数学上 [a, b)
  • a...b 相当于数学上 [a, b]
  • swift中没有全开区间的概念,即没有(a, b)的写法

swift中的for循环:

  • for后面的括号可以省略
  • swift3中已经移除了普通的for循环写法
  • forin写法:区间遍历
  • forin写法,如果不需要用到下标值,可以用下划线"_"省略

swift中的while循环

  • 在OC中,使用do while循环
  • 在swift中,使用repeat while循环

字符串

swift中的字符串为String类型,是个结构体.而OC中的NSString是对象,所以swift中的字符串类型比OC的效率高.

  • 定义字符串,可以不用指定String类型
  • 可以直接遍历字符串中的字符,使用for c in str.characters{}
  • 字符串的拼接
    • 直接使用str1+str2
    • 拼接其他标识符的字符串:使用(str)
    • 字符串的格式化:String(format:"%02d:%02d", arguments: [min, second])
  • 字符串的截取:可以先转换为OC的NSString类型,再进行截取
    • (urlString as NSString).substring(to: 3)
    • (urlString as NSString).substring(with: NSRange(location: 4, length: 5))
    • (urlString as NSString).substring(from: 10)

数组

  • 数组的定义:

    • 可变数组(使用let声明):let array = ["a", "b"]
    • 不可变数组(使用var声明):
      • var arrayM = Array()
      • var arrayM = [String]()
  • 对可变数组的操作:
    • 添加元素:arrayM.append("c")
    • 删除元素:arrayM.remove(at: 0)
    • 修改元素:arrayM[0] = "m"
    • 获取元素:arrayM[0]
  • 遍历数组:
    • for i in 0..<arrayM.count {}
    • for name in arrayM {}
    • for i in arrayM[0..<2] {}
  • 数组的合并:
    • swift中,如果两个数组类型是完全一致的,才可以进行相加合并.

字典

  • 字典的定义:

    • 不可变字典(let)

      • 注意:在swift中无论是数组还是字典,都使用[],但是如果[]中存放的是元素,编译器会认为是一个数组.如果[]中存放的是键值对,编译器会认为是一个字典.
      • let dict = ["key" : "value"]
    • 可变字典(var)
      • var dictM = Dictionary<String, AnyObject>()
      • var dictM = [String : AnyObject]()
      • 注意:一般在指定数据类型时,使用AnyObject,在声明变量类型时使用NSObject.
  • 对可变字典的操作:
    • 添加元素:dictM["newKey"] = "newValue"
    • 修改元素:dictM["key"] = "newValue",如果存在key,则覆盖该key之前的value,如果不存在key,则直接添加.
    • 删除元素:dictM.removeValue(forKey: "key")
    • 获取元素:dictM["key"]
  • 遍历字典:
    • 遍历所有的key:for key in dictM.keys {}
    • 遍历所有的value:for value in dictM.values {}
    • 遍历所有的key/value: for (key, value) in dictM {}
  • 合并字典:
    • 注意:即使两个字典的类型一致,也不能进行相加合并
    • 如果必须进行合并,可以遍历一个字典,将其逐个添加到另外一个字典中.

元组

元组一般用于函数的返回值,其与数组和字典功能类似,但是写法更为直观,所以swift中新增了元祖的类型.

  • 元组的基本写法:let userInfo = ("name", 18, 1.8)

    • userInfo.0
  • 给每一个元素起别名:let userInfo = (name: "name", age: 18, height: 1.8)

    • userInfo.name
  • 别名就是元组变量的名称

    • let (name, age, height) = ("name", 18, 1.8)
    • 直接使用name,age,height即可获取元组中元素的值

可选类型

可选类型的作用:当声明一个变量为String类型,而想要给它赋值为nil,需要使用可选类型.

  • 定义方式:

    • 方式一:基本定义方式,不常用,var name: Optional = nil
    • 方式二:语法糖,常用,var name: String? = nil
  • 给可选类型赋值:name = "abc"
    • 在使用可选类型时,拿到optional(具体的值)
  • 强制解包:
    • 通过在变量后使用"!"来进行强制解包
    • 注意:强制解包是非常危险的过程,在强制解包时,如果里面没有值,程序会发生崩溃.
    • 严谨的解包方式:if name != nil {}
  • 可选绑定:
    • 如果name不等于nil,则解包name,并且将解包后的值赋值给新值
    • 方式一(不常用):if let tempName = name {}
    • 方式二(常用):if let name = name {}
    • 以上操作其实可以分为两步:
      • 首先判断name是否有值
      • 如果有值,则进行强制解包(系统会默认处理),并且将解包后的值赋给前面的常量,并执行大括号里面的代码
      • 如果没有值,则不进行强制解包,同时也不执行括号里面的代码

可选类型的应用场景

在使用一个字符串创建URL类型的常量时,需要使用可选类型

因为如果字符串中包含中文时,创建的URL对象可能为空

在使用的时候,需要对可选类型进行判断,此时可以使用可选绑定,在大括号内创建NSURLRequest对象

函数

在OC中叫做方法,在swift中叫做函数

  • 没有参数,没有返回值

    • func about() -> Void {}
    • func about() {}
  • 没有参数,有返回值
    • func readMessage() -> String {}
  • 有参数,没有返回值
    • func callPhone(phoneNum : String) -> Void {}
    • func callPhone(phoneNum : String) {}
  • 有参数,有返回值
    • func sum(num1: Int, num2: Int) -> Int {}

函数的注意点

  • 注意一:内部参数和外部参数

    • 内部参数:在函数内部可以看到的参数就是内部参数,默认情况下所有的参数都是内部参数
    • 外部参数:在函数外部可以看到的参数名称就是外部参数,在swift3之前默认从第二个参数开始既是内部参数又是外部参数,但是从swift3开始,默认第一个内部参数也是外部参数.
  • 注意二:swift中的默认参数
    • func makeCoffe(coffeName: String = "雀巢") -> String {}
    • 在调用函数是,如果没有传递某个参数的值,swift会根据函数的声明,自动添加默认参数的值.
  • 注意三:可变参数
    • func sum(num: Int...) -> Int {}
  • 注意四:指针类型
    • swift函数参数,默认是值传递,在函数中直接交换两个参数的值,调用函数后,参数的值并不会发生改变.
    • func swapNum(m: inout Int, n: intout Int) {}
    • 调用时:swapNum(m: &m, n: &n)
  • 注意五:函数的嵌套使用(用的不多,了解即可)
    • 在函数内部,可以声明新的函数,如果不调用,则不会执行函数内的代码.
    • 只有在调用了函数,才会执行,哪里调用就在哪里执行.

Swift中类的注意事项

  1. 类的定义
  • 可以不继承任何类:class Person {}
  • 可以继承NSObject:class Person : NSObject {}
  • 不继承父类,可以使自定义的类更加轻量级.如果需要使用到NSObject中的属性或方法,则需要继承,比如使用KVC对属性进行赋值
  • 注意:任何一个类,都要保证它里面的属性,在类初始化的时候要有一个默认值.
  1. 创建类对应的对象
  • let p = Person()
  • let p: Person = Person()
  1. 给类的属性赋值
  • 可以通过点语法直接赋值
  • 也可以通过KVC,调用类对象的setValuesForKeys()方法
  1. 可以重写setValue...forUndefinedKey方法,那么字典中没有的字段可以在类中没有对应的属性,程序也不会报错.
  2. 如果要写的某一个方法是对父类方法的重写,那么必须在该方法前加上override关键字

定义Swift类中的属性

在swift中,声明的类属性都需要进行初始化,类属性分为三类:

  • 存储属性:

    • var age: Int = 0
    • var mathScore: Double = 0.0
    • var chineseScore: Double = 0.0
  • 计算属性:
    • 通过别的方式计算到结果的属性,称之为计算属性
    • var averageScore: Double { return (mathScore + chineseScore) * 0.5 }
  • 类属性:
    • 类属性是和整个类相关的属性,而且是通过类名进行访问
    • 在生成单例的时候,会用到类属性
    • static var courseCount: Int = 0

给类属性赋值:Student.courseCount = 2

创建对象:let stu = Student()

给对象的属性赋值:stu.age = 10

直接使用计算属性:let averageScore = stu.averageStudent

在swift开发中,如果使用当前对象的某一个属性,或者调用当前对象的某一个方法时,可以直接使用,不需要加self.但是在产生歧义的情况下,还是需要加上self的.

Swift中类的构造方法

swift中类的构造函数和OC中的初始化方法功能相同,只是写法不同.

在构造函数中,如果没有明确super.init(),那么系统会帮助调用super.init()

  • 自定义构造函数:

    • 参数非字典类型:init(name: String, age: Int) {}
    • 参数为字典类型:
      • 可以直接遍历字典,在遍历字典的时候,需要判断可选类型,然后转换可选类型,再使用可选绑定,对属性进行赋值
      • 也可以直接使用KVC,但是在调用setValueForKeys()前,需要调用父类的初始化函数super.init(),虽然系统会默认调用该函数,但是在自定义构造函数尾部才去调用,所以需要首先调用super.init().
      • 在使用KVC的时候,也需要重写setValue(forUndefinedKey)方法,以便处理类中没有定义key的属性.

属性监听器

class Person: NSObject {
// 属性监听器
var name : String? {
// 属性即将改变时进行监听
willSet {
print(name)
print(newValue)
} // 属性已经改变时进行监听
didSet {
print(name)
print(oldValue)
}
}
}

回顾OC中的block

使用block模拟网络请求中的回调

  • 自定义一个网络请求的工具类HttpTool,提供loadData方法
- (void)loadData:(void (^)(NSString *))callBack
{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"发送网络请求:%@", [NSThread currentThread]); dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"拿到数据,并且进行回调:%@", [NSThread currentThread]); callBack(@"json数据");
});
});
}
  • 在ViewController中通过点击屏幕,在ViewController中拿到block返回的数据
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
/*
__weak修饰的弱引用,如果指向的对象销毁,那么指针会立马指向nil(0x0)
__unsafe_unretained修饰的弱引用,如果指向的对象销毁,那么指针依然指向之前的内存地址,很容易产生'野指针'/'僵尸对象'
*/
__weak ViewController *weakSelf = self; [self.tools loadData:^(NSString *jsonData) {
// NSLog(@"在ViewController拿到数据:%@", jsonData);
weakSelf.view.backgroundColor = [UIColor redColor];
}];
}

闭包

闭包的写法:(参数列表) -> (返回值类型)

weakself?.view

  • 如果前面的可选类型,没有值,后面所有的代码都不会执行
  • 如果前面的可选类型,有值,系统会自动将weakself进行解包,并且使用weakself

闭包解决循环引用的三种方式:

  • 方式一(写法比较复杂):使用weak var weakSelf = self

    • 注意:必须使用var来声明,因为self可能会发生变化,如果使用let声明,编译器会报错.
  • 方式二(比较危险,当self指向nil时,可能会发生崩溃):tools.loadData {[unowned self] (jsonData) -> () in ... }
  • 方式三(常用写法):tools.loadData {[weak self] (jsonData) -> () in ... }

尾随闭包:如果闭包作为方法的最后一个参数,那么闭包可以将()省略掉

  • 普通写法:tools.loadData ({[weak self] (jsonData) -> () in ... })
  • 尾随闭包的写法一:tools.loadData() {[weak self] (jsonData) -> () in ... }

    - 但是闭包中可以直接使用self,而不需要进行解包
  • 尾随闭包的写法二(系统默认写法):tools.loadData {[weak self] (jsonData) -> () in ... }

注意:swift中的deinit()方法相当于OC中的dealloc方法,当对象销毁时,会调用该函数.

  • OC中使用__weak修饰self,当对象销毁时,self将指向nil(0x0)

  • OC中使用__unsafe__unretain修饰self,当对象销毁时,self仍指向原内存地址,会产生"野指针"错误或"僵尸对象",这个写法相当于swift中的unowned.

懒加载

  • 懒加载的介绍

    • swift中也有懒加载的方式.
    • 苹果的设计思想:希望所有的对象在使用时才真正加载到内存中
    • 和OC不同的是,swift有专门的关键字来实现懒加载
    • lazy关键字可以用于定义某一个属性懒加载
  • 懒加载的使用

    • 格式:lazy var 变量: 类型 = {创建变量的代码}()
// 懒加载的本质是,在第一次使用的时候,执行闭包
// 将闭包的返回值赋值给属性
// lazy的作用是只会赋值一次
lazy var array: [String] = {
() -> [String] in
return ["abc", "def", "ghi"]
}()

也可以写成下面这种方式

lazy var array: [String] = {
return ["abc", "def", "ghi"]
}()

Swift基本语法学习笔记的更多相关文章

  1. Golang 语法学习笔记

    Golang 语法学习笔记 包.变量和函数. 包 每个 Go 程序都是由包组成的. 程序运行的入口是包 main. 包名与导入路径的最后一个目录一致."math/rand" 包由 ...

  2. Swift高级语法学习总结(转)

    Swift高级语法学习总结 1.函数 1.1 func funcNmae()->(){} 这样就定义了一个函数,它的参数为空,返回值为空,如果有参数和返回值直接写在两个括号里就可以了 1.2 参 ...

  3. Swift基础语法学习总结(转)

    Swift基础语法学习总结 1.基础  1.1) swift还是使用// 和/* */ 来注释,并且/* */允许多行注释. 1.2) swift使用print和println打印,它的传参是一个泛型 ...

  4. Swift高级语法学习总结

    Swift基础语法学习总结Swift高级语法学习总结Swift语法总结补充(一) 1.函数 1.1 func funcNmae()->(){} 这样就定义了一个函数,它的参数为空,返回值为空,如 ...

  5. Swift基础语法学习总结

    Swift基础语法学习总结Swift高级语法学习总结Swift语法总结补充(一) 1.基础  1.1) swift还是使用// 和/* */ 来注释,并且/* */允许多行注释. 1.2) swift ...

  6. MarkDown语法 学习笔记 效果源码对照

    MarkDown基本语法学习笔记 Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式. 下面将对Markdown的基本使用做一个介绍 目 ...

  7. 毕业设计 之 五 PHP语法学习笔记

    毕业设计 之 四 PHP语法学习笔记 作者:20135216 平台:windows10 软件:XAMPP,DreamWeaver 说明:该笔记是对网站编程语言的详细学习 一.PHP基础 0. 关于环境 ...

  8. doy05循环语法学习笔记

    doy05循环语法学习笔记 一.while循环语法: 1.基本用法示例 x = 1 while x <= 5: print(x) x += 1 2.死循环:永远不结束的循环 如:while Tr ...

  9. swift语言的学习笔记

    swift参考了OC,Rust,Haskell,Ruby,Python,C#等语言的特性.首先,学习这门语言是速学的,我不想浪费太多时间在笔记这门语言和其他语言的哪里不同,特性你自己亲自实践就知道了. ...

随机推荐

  1. PC110302/UVA10010

    下周开始就省选了,ACM的日子在今年内应该就会结束了,大三了,最后一次机会了,小小感伤一下-- 今天广州下大雨,心情怪怪的,感觉码不出质量高的,又很久没做过PC了,就刷刷水题吧. 老实说Program ...

  2. ACM Sdut 2158 Hello World!(数学题,排序) (山东省ACM第一届省赛C题)

    题目描述 We know thatIvan gives Saya three problems to solve (Problem F), and this is the firstproblem. ...

  3. 【elasticsearch】(2)centos7 超简单安装elasticsearch 的监控、测试的集群工具elasticsearch head

    elasticsearch-head是elasticsearch(下面称ES)比较普遍使用的可监控.测试等功能的集群管理工具,是由H5编写的单独的网页程序.使用方法网上很多,这里教大家一个超简单安装h ...

  4. 怎样让老浏览器兼容html5新标签

    CSS样式设置默认样式: <style> article, aside, canvas, details, figcaption, figure, footer, header, hgro ...

  5. float浮动引起的ul高度崩溃与overflow的关系

        今天遇到的问题真的让人不得不吐槽,因为一个很小的问题,花费了半天的时间来才解决这个问题.一直认为自己对Html与Css了解应该算蛮不错的,但是今天遇到的事情让我不得不反省自己的学习心态上的错误 ...

  6. Linux下安装gcc 、g++ 、gfortran编译器

    一.ubuntu下gcc/g++/gfortran的安装 1.安装 (1).gcc ubuntu下自带gcc编译器.可以通过“gcc -v”命令来查看是否安装. (2).g++ 安装g++编译器,可以 ...

  7. ubuntu使用github

    Ubuntu下安装Git Ubuntu12.04 LTS默认是已经安装Git的,可以使用 git --version 测试是否安装.如果没有安装,使用命令: sudo apt-get install ...

  8. WPF后台访问XAML元素

    当我们需要从后台访问xaml文件时,我们可以通过这样的方式来操作: private void button1_Click(object sender, RoutedEventArgs e) { Sys ...

  9. maven web项目不能创建src/main/java等文件夹的问题

    eclipse创建maevn web项目,在选择maven_archetype_webapp原型后,默认只有src/main/resources这个Source Floder.  按照maven目录结 ...

  10. 第一个deeplearning4jproject跑起

    deeplearning4j是基于java的深度学习库,当然,它有许多特点,但暂时还没学那么深入,所以就不做介绍了 需要学习dl4j,无从下手,就想着先看看官网的examples,于是,下载了exam ...