简介
Swift是苹果公司推出的可用于开发Mac OS和iOS系统上的应用的专用编程语言,它相比于Objective-C(以下简称OC)语言,更加严谨,是一种强语言。
使用工具
首先,先介绍使用的工具,毕竟一个方便的工具可以大大提高效率,而这里学习Swift最快速地工具就是playground
1
playground 游乐场,可以立刻获得编译后的效果
快速入门
- 创建对象
- OC
[[UIView alloc] initWithXXX:];
- Swift
UIView(xxx)
- 调用方法
- OC
[UIColor redColor]
- OC
- Swift
UIColor.redColor
- 枚举
- OC
UIButtonTypeContactAdd
- Swift
UIButtonType.ContactAdd
- OC
输出
- OC
NSLog(@"Hellow World");
- Swift
print("Hellow World");
常量变量
- OC
- 变量
int a = 20;
- 常量
const int a = 20
- 变量
- Swift
- 在Swift语言中,所有的类型的第一个字母均是大写,Int,Double...
- 变量 - var
var a1:Int = 20
- 常量 - let
let a1:Int = 20
3
-
快捷键: 按住option,点击,可以查看他的信息
4 -
数据类型
- OC中的数据类型首字母变成大写,就是Swift中的数据类型
-
注意点:
- 在Swift开发中,一般情况下应该先用let,只要在需要修改数据时才改用var,使用let的
好处
是,避免数据被修改,可以保证数据安全性
- 在Swift开发中,一般情况下应该先用let,只要在需要修改数据时才改用var,使用let的
-
类型推断
- Swift中如果在定义变量/常量时进行初始化, 那么数据类型可以不用写, 系统会自动根据右边的复制推导出变量/常量的类型
- Swift开发中
能不写
数据类型就不写
数据类型, 尽量使用编译器的自动推导 - 只有当我们需要明确的指定数据的长度, 获取需要先定义再初始化时才明确的指定数据类型
- 使用自动类型推导
好处
: 大大降低
代码中的冗余
代码 - 指定类型
let num:Int = 20
- 自动推导
let num = 20
- 类型转换:
- OC中有显示转换和隐式转换
double value = 10.1 + 9
- Swift中只有显示转换没有隐式转换, 也就是说只有相同类型的数据才能进行赋值和计算
- OC中有显示转换和隐式转换
元组
-
复合
数据类型 - 只要将多个相同或者不同的数据用
()
括起来就是元祖 - 优点: 在以前没有元祖之前C和OC语言是通过传入指针或者返回结构体的方式来返回多个值的, 而有了元祖之后就可以实现让一个函数返回多个值
let number1:(Int,Double,CGFloat,NSInteger) = (1,1.1,1.11,2)
number1.0
number1.1
number1.2
number1.3
// 给元组的元素起名
/*
元祖的其它定义方式:指明应用元祖元素的名称
*/
let person = (name:"tym", age:18, score:100.0)
person.name
person.age
person.score
// 提取元组的数据
/*
元祖的其它定义方式:
通过指定的名称提取元祖对应的值, 会将对应位置的值 赋值给对应位置的名称
*/
let (name, age, score) = ("tym", 18, 100.0)
name
age
score
/*
如果不关心元祖中的某个值可以利用_通配符来忽略提取
*/
let (name1 , age1 , _) = ("tym", 18, 99.8)
print(name1)
print(age1)
分支
-
Bool 类型
- C 和OC并没真正的Bool类型,非0即真
- OC语言的Bool类型YES/NO是
typedef signed char BOOL;
- OC语言的Bool类型YES/NO是
- Swift引入了真正的Bool类型
- Swift中没有C和OC中非零即真的概念
- Swfit中逻辑值只有两个true/false
- C 和OC并没真正的Bool类型,非0即真
-
if语句
- Swift
- 大部分用法和OC中一致
- Swift中
条件
语句可以不用写()
- OC中如果if后面只有一条语句, 那么{}可以省略, 但是Swift不行
- OC中条件语句可以是任何数值, OC中非0即真, YES/NO
- Swift中
条件
语句的取值必须
是Bool
类型, 也就是说Swift中提供了真正的Bool类型, true/false
- Swift
let number = 10
//if number = 10 // Swift有效的避免了这种问题
if number == 10
{
print(number)
}
- 三目运算符
- 大部分用法和OC一样
- 条件表达式只能是Bool值
print(age >= 18 ? "开网卡":"回家")
- switch语句
- 大部分用法和OC一样
- Swift中
条件
语句可以不用写()
-
OC
中default
可以省略
, 而Swift
中大部分情况不能省略,而且default只能够放在最后面的位置 - OC中default的位置可以随便写, 而Swift不可以
- OC中每个case后面必须加上break, 否则会出现
穿透
, 而Swift
不会穿透, 也就是说不用写break
- OC中要在case中间定义变量必须加上{}, 否则作用域混乱, 而Swift不用
- Swift可以
判断
对象类型,区间和元祖,OC只可以判断整数
let score = 100
switch score
{
case 59:
print("不及格")
case 100:
print("满分")
default:
print("Other")
}
var rank = "A"
switch rank{
case "A": //相当于if
print("优")
case "B": // 相当于else if
print("优")
case "C": // 相当于else if
print("优")
default: // 相当于else
print("没有评级")
}
/*
因为不能穿透所以不能这么写
var rank1 = "A"
switch rank1{
case "A":
case "B":
print("优")
case "C":
print("优")
default:
print("没有评级")
}
*/
//只能这么写
var rank1 = "A"
switch rank1{
case "A", "B": // 注意OC不能这样写
print("优")
case "C":
print("差")
default:
print("没有评级")
}
- 区间
- 闭区间: 0...10 , 取值范围0~10,包含头包含尾
- 半闭区间: 0..<10 , 取值范围0~9,包含头不包含尾
switch score
{
case 0..<60: // 0 ~ 59
print("不及格")
case 60..<80: // 60 ~ 79
print("良好")
case 80..<100: // 80 ~ 99
print("优秀")
default:
print("满分")
}
// 判断元组
let point = (100, 50)
switch point
{
case (0,0):
print("原点")
case (50,50):
print("中点")
case (100,100):
print("右下角")
default:
print("Other")
}
// 值绑定
var point = (1, 10)
switch point{
case (var x, 10): // 会将point中X的值赋值给X
print("x= \(x)")
case (var x, var y): // 会将point中X,Y的值赋值给X,Y
print("x= \(x) y= \(y)")
case var( x, y):
print("x= \(x) y= \(y)")
default:
print("Other")
}
// 根据条件绑定
var point = (100, 10)
switch point{
// 只有where后面的条件表达式为真才赋值并执行case后的语句
case var(x, y) where x > y:
print("x= \(x) y= \(y)")
default:
print("Other")
}
可选类型
- 可选类型
- 一个变量
可以有值
也可以没有值
, 我们就称之为可选类型 - 在Swift中如果使用一个可选类型的变量/常量, 必须
解包
操作- 解包: 只需要在变量/常量后面加上 !
- !含义: 代表
告诉系统
该变量/常量中一定有值
, 如果强制解包一个没有值的常量/变量,那么会报错
- 优点: 提高
代码阅读性
- 格式:
- 修饰符 变量名称:Optional<数据类型>
- 修饰符 变量名称: 数据类型?
- 语法糖: 因为在Swift中可选类型用得非常非常多, 所以为了简化代码, Swift提供了一个语法糖, 可以用?
代替
Optional<数据类型>
- 一个变量
7
- 注意:
- 在开发中一般情况下尽量不要
强制
解包一个可选类型, 否则会引发错误 - 可选绑定: 为了更
安全
的解析可选类型的值, 一般情况下使用可选绑定- 如果没有值就不会做任何操作, 如果
有值
会返回true
并将optValue的值赋
值给result执行大括号中的内容
- 如果没有值就不会做任何操作, 如果
- 在开发中一般情况下尽量不要
/*
// 这样不严谨
let url = NSURL(string: "http://www.hao123.com/")
print(url)
let request = NSURLRequest(URL: url!)
*/
let url = NSURL(string: "http://www.hao123.com")
print(url)
if url != nil
{
let request = NSURLRequest(URL: url!)
}
// 可选绑定: 如果url不为nil, 系统内部就会自动将解包之后的值赋值给temp, 并且只有temp有值时才会执行{}中的代码
// Swift开发中推荐这种写法
if let temp = url
{
let request = NSURLRequest(URL: temp)
}
循环语句
- for循环
- 传统的for
/*:
传统for
* 基本用法和OC一致
* for后面的()可以省略
* for后面的{}不可用省略
* Swift开发中不建议使用传统for循环
*/
for var i = 0; i < 10; i++
{
print(i)
}
// 一直循环
//for ;;
//{
// print("---")
//}
- 推荐的for循环形式
// Swift开发者中推荐的for循环格式
for i in 0..<10
{
print(i)
}
- while 循环
- 基本用法和OC一致
var number = 0
while number < 10
{
print(number)
number++
}
- do-while 循环
- 基本用法和OC一致
- Swift2.0开始dowhile循环中没有do, 只有repeat, 因为do被作用异常处理
var index = 0
repeat{
print(index)
index++
}while index < 10
数组
- 格式 var arr: Array<Int> / var arr: [Int]
- 可变和不可变 var/let
// 1.遍历数组(取值)
arr[0]
for item in arr
{
print(item)
}
// 2.添加
arr.append(3)
// 3.修改
arr[1] = 9
// 4.删除
arr.removeAtIndex(0)
// 5.合并
var arr1 = [3, 5, 7]
arr += arr1
// 6.Swift特殊
for item in arr[0..<2] // 0~1
{
print(item)
}
//arr.removeRange(Range(start: 0, end: 2))
//arr
// 通过观察可以发现Range其实就是一个半闭区间
arr.removeRange(0..<2)
arr
arr += arr1[0..<2]
字典
- 格式 var dict: Dictionary<String, String>
- 注意: 将OC的{}换成了[]
- 可变和不可变 var/let
var dictTest: Dictionary<String,String>
var dictTest2: [String: String]
var dict = ["name":"tym", "age":"18"]
// 企业开发中字典使用的最多的类型就是 [String: NSObject] 类型
var dict2 = ["name":"tym", "age":"18", "score":99.99]
// 取值
dict2["age"]
// 修改
dict2["age"] = 20
dict2
// 增加
dict2["rank"] = 10
dict2
// 删除
dict2.removeValueForKey("name")
dict2
// removeValueForKey返回一个可选类型, 如果字典中不存在需要删除的key, 那么返回nil并且不会执行任何操作, 如果存在则删除key对应的值, 并且返回被删除的值
var dict14 = ["name":"lnj", "age":30]
if let orignal = dict14.removeValueForKey("names")
{
print(dict14)
print(orignal)
}
print(dict14)
var dict15 = ["name":"lnj", "age":30]
dict15.removeAll(keepCapacity: true)
// 遍历
var dict17 = ["name":"lnj", "age":30]
for key in dict17.keys
{
print("key = \(key)")
}
var dict18 = ["name":"lnj", "age":30]
for value in dict18.values
{
print("value = \(value)")
}
// Swift写法
// 系统会自动将字典中的key赋值给元祖中的第一个遍历, 会自动将字典中的value赋值给元祖中的第二个遍历
for (key,object) in dict2
{
print(key)
print(object)
}
// 合并
var dict3 = ["name":"tym", "sex":"M", "height":179.9]
var dict4 = ["weight":120, "score":100.0]
for (key,value) in dict4
{
dict3[key] = value
}
dict3
字符串
- OC的字符串是NSString, Swift的字符串String
- OC的字符串是一个对象, Swift字符串是一个
结构体
, 效率更高 - OC中的字符串是一个\0结尾, Swift字符串
不是
以\0结尾 - Swift中的字符串支持遍历
let str = "Hi, \0 Tym"
// 遍历字符串
for c in str.characters
{
print(c)
}
// 字符串拼接
var str2 = "Hello,World!"
str2 += str
// 字符串格式化
let name = "tym"
let age = 18
let res = "name: \(name) , age: \(age)"
// 2015-10-19 13:55
let str3 = String(format: "%d-%02d-%02d %02d:%02d", arguments: [2015,10,19,13,55])
// 截取字符串
// 提示: 在Swift开发中, 我们经常需要将Swift的字符串转换为OC的字符串来操作, 并且Swift自身也意识到了这一点, 所以在OC字符串和Swift的字符串之间转换相当简单
let str4 = "ttyymm"
let str5: NSString = str4
str5.substringToIndex(4)
str5.substringWithRange(NSMakeRange(0, 1))
// 计算字符串长度
var stringValue = "abc李"
print(stringValue.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
// 打印结果6, 和C语言一样计算字节数
// as 就是把什么当做什么
(str4 as NSString).substringFromIndex(2)
函数
- 格式
func 函数名称(形参列表) ->返回值类型
{
代码
}```
* Void == ()
```objc
// 1.没有参数没有返回值,没有返回值时可不写返回值
func say() -> Void
{
print("Hi!")
}
func say1() -> ()
{
print("Hi!")
}
say1()
func say2()
{
print("Hi!")
}
say2()
// 2.有参数没有返回值
// Swift2.0开始, 会自动将形参列表的第二个参数名称作为标签
// Swift2.0之前是没有这个特性的, 在Swift2.0之前如果需要显示标签需要在形参名称前面加上#
func sum(num1:Int, num2:Int)
{
print(num1 + num2)
}
sum(10, num2: 20)
// 3.没有参数有返回值
func getNumber() -> Int
{
return 998
}
getNumber()
// 4.有参数有返回值
func sum2(num1:Int, num2:Int) -> Int
{
return num1 + num2
}
print(sum2(11, num2: 22))
- 内部和外部参数
- 默认情况下所有形参都是
内部参数
, 也就是说只能在函数内部
使用 - 从Swift2.0开始会自动将形参列表的第二个参数名称作为标签, 也就是说
从第二个
参数开始, 参数的名称既是内部参数
又是外部参数
- 如何指定外部参数? 在方法中的参数的前面加上
外部参数名
- 默认情况下所有形参都是
// 这里的yy就是外部参数
func sum3(num1:Int, yy num2:Int)
{
print("num1: \(num1), num2: \(num2)")
}
//sum3(100, num2: 200)
sum3(100, yy: 300)
- 默认参数
- 如果指定了默认值, 那么在调用方法的时候就
可以不用
传递数据, 如果不传递数据系统就会使用默认值, 如果传递了就会使用传递的值 - 在其它语言里面, 默认值一般情况只能是最后一个参数, 但是Swift可以写在任何位置
- 构造方法中,不能设置默认参数
- 如果指定了默认值, 那么在调用方法的时候就
func joinSting(str1: String, str2: String = "是", str3: String) -> String
{
return str1 + str2 + str3
}
joinSting("tym", str2: "不是", str3: "帅哥")
joinSting("tym", str3: "帅哥")
- 常量参数、变量参数以及inout参数
-
默认
情况下所有形参都是常量
参数, 不能在函数中修改形参的值 - 如果想在函数中修改形参的值, 那么必须把形参变为变量参数
- 和OC一样, 在函数中修改形参的值
不会影响
到外面实参的值 - 如果想在函数中修改形参之后
影响
实参, 那么必须把形参变为inout参数
-
//func swap(a: Int, b: Int)
//{
// let temp = a
// a = b // 不能修改常量
// b = temp
//}
//func swap(var a: Int,var b: Int)
//{
// let temp = a
// a = b
// b = temp
// print("a = \(a), b = \(b)")
//}
//var a = 23
//var b = 24
//swap(&a, &b)
//
func swap1(inout a: Int,inout b: Int)
{
let temp = a
a = b
b = temp
print("a = \(a), b = \(b)")
}
var a1 = 23
var b1 = 24
print("a = \(a1), b = \(b1)")
swap1(&a1, b: &b1)
print("a = \(a1), b = \(b1)")
- 可变参数
- 只要参数是可变参数, 就可以传递
一个
或多个
值 - 在其它语言中一般情况下可变参数只能是最后一个形参, 而Swift中可以写在任意位置, 但是为了提高代码的阅读性, 还是建议写在最后
- 只要参数是可变参数, 就可以传递
func sum4(numbs:Int..., temp:Int , temp2: Int) -> Int
{
var sum = 0
for i in numbs
{
sum += i
}
return sum + temp + temp2
}
sum4(3, temp: 10, temp2: 20)
- 函数嵌套
- 将一个函数写到另外一个函数的函数体中, 外面称之为函数嵌套
- 1.被嵌套的函数只能在
父函数
内部访问 - 2.被嵌套的函数可以访问
外部
的变量
- 1.被嵌套的函数只能在
- 应用场景: 两个函数之间依赖较强, 或者一个函数就只给另外一个函数使用
- 例如: 对数组排序是一个函数, 交换变量又是一个函数, 他们就可以使用函数嵌套
- 将一个函数写到另外一个函数的函数体中, 外面称之为函数嵌套
let value = 23
func test(inout a:Int)
{
let number = 10
func demo()
{
print("\(number)", "\(a)", "\(value)")
}
demo()
}
var tes = 110
test(&tes)
构造函数
- 当重写一个类的构造方法时,这个类会暗自帮我们调用super.init()
- 定义属性,直接写在class里面
- 必须给这个类中所有的属性进行初始化
- 如果不能在创建对象时给这个类中所有的属性进行初始化,那么这些属性必须是可选的(?)
- 注意:
- 如果自定义一个类, 并且没有重写构造方法, 那么系统会提供默认的构造方法
- 如果自定义一个类, 并且自定义了构造方法, 并且没有重写原始的构造方法,那么系统不会提供默认的构造方法
- 如果还需要原来的构造方法,需要重写该构造方法(尽管里面什么都不处理)
- Swift中要求在
创建
一个类时必须给这个类中所有的属性
进行初始化
- 如果不能在创建对象时给这个类中
所有的属性
进行初始化
, 那么这些属性必须
是可选的
- 如果已经在构造方法中对所有的属性进行了初始化, 那么这些属性就可以不是可选类型
- 在给某一个类指定属性的数据类型时, 如果该属性是对象类型, 那么可以指定为可选类型
- 如果该属性不是对象类型而是
基本数据
类型, 那么建议直接赋值为0
- 如果属性是
基本数据
类型, 并且是可选
类型, 系统不会
自动分配存储
空间,在KVC的时候会出现问题
- 如果属性是
- 如果不能在创建对象时给这个类中
var name: String?
var age: Int = 0
// 重写构造方法
override init() {
// 注意: 在构造方法中必须先初始化本类再初始化父类
name = "tym"
age = 18
// 当我们重写一个类的构造方法时, 系统内部会悄悄得帮我们调用super.init()
super.init()
}
// 自定义构造方法
init(name: String, age: Int) {
self.name = name
self.age = age
// 以下这句代码,能不写就不写
// super.init()
}
init(dict: [String: NSObject]) {
// 注意:Swift中如果想在构造方法中使用KVC转换模型, 必须先调用 super.init()
// 调用 super.init()的目的主要是为了给对象分配存储空间
super.init()
setValuesForKeysWithDictionary(dict)
}
// Swift中打印对象,会调用以下属性,重写此属性,方便测试
override var description: String {
// return "name:\(name), age:\(age)"
let keys = ["name","age"]
let dict = dictionaryWithValuesForKeys(keys)
return "\(dict)"
}
setter、getter方法
- OC
- setXXX
- getXXX
- Swift
- willSet、didSet
- get
- 如果只是想重写一个属性的get方法,可以直接return
var name: String?
{
// 在Swift开发中用以下两个方法代替OC中的重写setter方法
willSet{
print("赋值之前的调用\(newValue)")
}
didSet{
print("赋值之后的调用\(oldValue)")
}
}
var age: Int
{
// 在Swift中如果只重写了get方法, 那么该属性就是一个只读属性readOnly
// 如果一个属性只重写了get方法, 我们也称之为"计算型属性", 计算型属性是不具备存储能力的
// get{
// return 110
// }
// 如果只是想重写一个属性的get方法, 那么可以简写
return 120
}
闭包
- OC
- block类似于匿名函数,用于封装代码块,在特定的时候执行一些耗时操作
- 类型格式:
返回类型 (^block名字)(参数列表)
- 值格式: ^(形参列表){
需要执行的代码
}
<returnType>(^<blockName>)(<parameterTypes>) = ^(<parameters>) {
<statements>
};
```objc
@implementation ViewController
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self loadData:^{
NSLog(@"刷新UI");
}];
}
-(void)loadData:(void (^)())finishBlock {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"%@",[NSThread currentThread]);
NSLog(@"加载数据");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"%@",[NSThread currentThread]);
finishBlock();
});
});
}
@end
- Swift
- 闭包是用于定义函数(Swift中函数就是闭包,闭包是一个特殊的函数),执行一些耗时操作
- 类型格式:(形参列表)->返回值类型
- 值格式:
{
(形参列表)->返回类型
in
需要执行的代码
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
loadData ({ () -> () in
print("刷新UI")
})
}
func loadData(finish:()->()) {
dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
print(NSThread.currentThread())
print("更新数据")
dispatch_async(dispatch_get_main_queue(), { () -> Void in
print(NSThread.currentThread())
finish()
})
}
}
}
- 闭包的写法
- 完整写法
loadData ({ () -> () in
print("更新UI")
})
+ 如果闭包`没有形参`, 那么in和in之前的代码都可以省略
```objc
loadData ({
print("更新UI")
})
- 如果闭包是函数的
最后一个参数
, 那么闭包可以写在函数()的后面
loadData ( ){ () -> () in
print("更新UI")
}
- 如果函数
只有一个闭包参数
, 那么函数的()可以省略
loadData {
print("更新UI")
}
- 闭包的循环引用问题
- OC
- __weak : 如果对象释放, 会自动设置为nil
- __unsafe_unretained: 如果对象释放, 不会自动设置为nil
__weak typeof(self) weakSelf = self
- Swift
- 对应关系: _weak == weak , _unsafe_unretained == unowned
weak var weakSelf = self loadData { () -> () in print("刷新UI") weakSelf!.view.backgroundColor = UIColor.greenColor() }
// 不建议此方法,因为强制解包了 loadData { [weak self] () -> () in print("刷新UI") self!.view.backgroundColor = UIColor.greenColor() }
- OC
// 因为unowned相当于_unsafe_unretained,不会设置成nil,所有不用强制解包
loadData { [unowned self] () -> () in
print("刷新UI")
self.view.backgroundColor = UIColor.greenColor()
}
```
-
单例
- OC
@interface Dog : NSObject + (instancetype)sharedDog; @end @implemetion Dog +(instancetype)sharedDog { static Dog *_instance = nil; // onceToken默认等于0, 只要执行一次之后就不等于0了, 原理是通过判断onceToken是否等于0决定是否需要执行block static dispatch_once_t onceToken; NSLog(@"%ld",onceToken); dispatch_once(&onceToken, ^{ _instance = [[self alloc] init]; }); return _instance; }
- Swift
- 注意:在func前添加class标记,相当于是类方法,不添加,相当于是对象方法
// 方法一 static var onceToken:dispatch_once_t = 0; static var _instance:Dog? class func sharedDog() -> Dog { print(onceToken) dispatch_once(&Dog.onceToken) { _instance = Dog() } return _instance! } // 方法二 // 因为是常量,所以只能赋值一次 static let _instance:Dog = Dog() class func sharedDog()->Dog { return _instance } // 方法三,强烈推荐的方法 // 而且苹果有统一的命名规范, 但凡是单例统一是shareInstance static let shareInstance:Dog = Dog()
懒加载
- 延迟存储属性
- Swift语言中
所有
的存储属性
必须有初始值, 也就是当构造完一个对象后, 对象中所有的存储属性必须有初始值, 但是也有例外, 其中延迟存储属性可以将属性的初始化推迟
到该属性第一次被调用的时候
- Swift语言中
- 懒加载应用场景:
- 1.有可能不会用到
- 2.依赖于其它值
- 格式:
- lazy var 变量: 类型 = { 创建变量代码 }()
- 懒加载的写法本质上是定义并执行一个闭包
lazy var demoView: UIView = {
let v = UIView(frame: CGRectMake(10, 10, 100, 100))
v.backgroundColor = UIColor.redColor() return v
}()
gurad
- �苹果公司意识到Swift编写的代码,会不知不觉得多层嵌套,然后代码变得非常丑陋,所以在Swift2.0的时候,专门推出了一个条件语句guard
- gurad 专门守护安全的
- 格式:
guard 条件语句 else {
需要执行的语句
return
}```
- 特点:只有条件为假的时候,才会执行else中的代码,相对于if else,这个只有else
- 作用: 用于过滤数据
---
# private
- 在Swift中,添加一个属性或者方法可以在其他项目中的文件访问
- 为了封装性,可以添加private在属性或者方法或者类前,可以让该属性或者方法只能在`当前`文件中访问
- 注意:
+ 由于点击事件是由NSRunLoop发起的,并不是当前的类发起的,如果在点击方法前添加private,那么NSRunLoop无法找到该方法,会导致崩溃
+ OC是基于运行时动态派发事件的
+ Swift是编译时就已经确定了方法
---
# @objc
- 想给监听点击事件的方法加上private,并且又想让系统动态派发时找到该方法,可以在该方法前加上@objc,@objc就能让这个方法支持动态派发
```objc
@objc private func composeBtnClick()
{
}
便利构造方法
- 在Swift开发中,如果想要快速创建一个对象,那么可以提供一个便利构造器(遍历构造方法)
- 在普通构造方法前面加上一个
convenience
,那么这个构造方法就是一个便利构造方法 - 注意:
- 如果定义一个便利构造器,那么
必须
在便利构造方法中调用指定构造方法
(没有convenience单词的构造方法)
- 如果定义一个便利构造器,那么
// 以下方式的确可以快速创建一个对象,但是Swift不是这种风格
class func createBtn(image:String, backgroundImage:String)->UIButton
{
let btn = UIButton(type: UIButtonType.Custom)
btn.setImage(UIImage(named: image), forState: UIControlState.Normal)
btn.setImage(UIImage(named: image + "_highlighted"), forState: UIControlState.Highlighted)
btn.setBackgroundImage(UIImage(named: backgroundImage), forState: UIControlState.Normal)
btn.setBackgroundImage(UIImage(named: backgroundImage + "_highlighted"), forState: UIControlState.Highlighted)
btn.sizeToFit()
return btn
}
/*
定义便利构造器步骤:
1.编写一个构造方法
2.在构造方法前面加上 convenience
3.在构造方法中调用当前类的其他"非便利构造器"初始化对象
*/
convenience init(imageName: String, backImageName: String)
{
self.init()
// 1.设置背景图片
setBackgroundImage(UIImage(named: imageName), forState: UIControlState.Normal)
setBackgroundImage(UIImage(named: imageName + "highlighted"), forState: UIControlState.Highlighted)
// 2.设置普通图片
setImage(UIImage(named:backImageName), forState: UIControlState.Normal)
setImage(UIImage(named: backImageName + "highlighted"), forState: UIControlState.Highlighted)
sizeToFit()
}
网友评论