Swift筆記
Any AnyObject NSObject
Int
Double
String
struct
都是結(jié)構(gòu)體
-
Any
: 一個協(xié)議聲明 -
AnyObject
: 一個具體的協(xié)議向拆,協(xié)議里面沒有內(nèi)容鹃操,默認(rèn)情況下汞斧,所有的類答姥,都遵循了這個協(xié)議 -
NSObject
:NSObject
類
條件判斷
swift中沒有非零即真和零為假的說法,只有嚴(yán)格的
Bool(true/false)
1. if的使用
let a = 1
if a == 1 {
print("test")
}else if a == 2{
print("sss")
}else {
print("wwqw")
}
2. 三目運(yùn)算符
a == 1 ? print("first") : print("hello")
3. guard
guard
條件成立闹丐,繼續(xù)往下走,不成立執(zhí)行else
里面的語句else
后要跳出語句被因,配合return
,continue
,break
,throw
等使用
func funcTest() {
let a = 1
guard a == 1 else {
print("a != 1")
return
}
print("a == 1")
}
4. switch的用法
1. switch與基本數(shù)據(jù)
// 必須要加default, 但是有些情況可以不加卿拴,例如枚舉的各個情況都判斷過了
// 判斷類型 可以是浮點(diǎn)型,String梨与,對象堕花。
let a = 11
switch a {
case 1, 11:
print("1, 11")
fallthrough // 會有穿透效果粥鞋,如果這個case為true,也執(zhí)行下個case的內(nèi)容
case 2:
print("2")
default:
print("不知道")
}
2. switch與區(qū)間
let score = 10.0
switch score {
case 0 ..< 60:
print("不及格")
case 60 ..< 90:
print("及格")
case 90 ..< 100:
print("優(yōu)秀")
default:
print("default")
}
3. switch與枚舉
enum Direction {
case up
case down
case left
case right
}
let rr = Direction.right
switch rr {
case Direction.up:
print("up")
case Direction.down:
print("down")
case Direction.left:
print("right")
case Direction.right:
print("right")
//default: // 此時可以省略default缘挽,因為各個情況都已經(jīng)判斷過,default也不會執(zhí)行
// print("ss")
}
4. switch與元組
let point = (10, 25)
switch point {
case (0, 0):
print("坐標(biāo)在原點(diǎn)")
case (1...10, 10...20): // 可以在元組中再加上區(qū)間
print("坐標(biāo)的X和Y在1~10之間")
case (_, 0): // X可以是任意數(shù)
print("坐標(biāo)的X在X軸上")
case (var x, var y): // x,y來接收參數(shù) 一定為true
print("333")
case var(x,y): where x > y // x,y來接收參數(shù) x>y則一定為true
print("1111")
default:
print("Other")
}
循環(huán)
1. for循環(huán)
for i in 0 ..< 10 {
print(i)
}
// _代表忽略的意思
for _ in 0 ..< 10 {
print("test")
}
2. while循環(huán)
1. while循環(huán)
var i = 10
while i > 0 {
i -= 1
print(i)
}
2. repeat~while循環(huán)
// do 特殊含義,捕捉異常
repeat {
i += 1
print(i)
} while i < 10
字符串處理
let str2 = "123"
let int4 = 10
// 字符串拼接
str2 + "\(int4)"
// 遍歷字符串
for i in str2.characters {
print(i)
}
str2.lengthOfBytes(using: String.Encoding.utf8)
str2.characters.count
String(format: "%02d", 1)
// 截取字符串
str2.substring(from: str2.startIndex)
str2.substring(to: str2.index(after: str2.startIndex))
str2.substring(from: str2.index(str2.startIndex, offsetBy: 2))
str2.substring(from: str2.index(str2.endIndex, offsetBy: -1))
let range = str2.startIndex ..< str2.endIndex
str2.substring(with: range)
str2.replaceSubrange(range, with: "sss")
// 轉(zhuǎn)為OC的NSString處理
let str3 = (str2 as NSString).substring(to: 2)
數(shù)組
// 數(shù)組的聲明和初始化
let arr1 = [2]
var arr2 : [Any] = [1, 2, "ii", 11, "ss", "w"]
let arr3 = [1, 1.1, "ss"] as [Any]
// 相同類型的數(shù)組可以直接相加
arr2 + arr3
// 獲取
arr2.first
arr2.last
arr2[0]
// 追加
arr2.append(2.0)
// 修改
arr2[0] = 1
// 插入
arr2.insert("sww", at: 2)
// 刪除
arr2.remove(at: 0)
arr2.removeFirst()
arr2.removeFirst(1)
// 操作數(shù)組的區(qū)間
let rang2 = 0 ..< 2
arr2.removeSubrange(0 ..< 2)
// 獲取數(shù)組最大最小
var arr = [1, 2]
arr.min()
arr.max()
var arr4 = ["a", "3.3"]
// 比的ASCII碼
arr4.min()
arr4.max()
// 數(shù)組的遍歷
for i in 0 ..< arr2.count {
print(arr2[i])
}
// 利用元組獲取數(shù)組的 角標(biāo)+ 值
for (key ,value) in arr2.enumerated() {
print(key, value)
}
for i in arr2[0...2] {
print(i)
}
// 轉(zhuǎn)為OC數(shù)組的遍歷
(arr2 as NSArray).enumerateObjects({ (value, idx, stop) in
print(value, idx)
})
字典
var dict : [String : Any] = ["key" : 1, "key2" : "value"]
dict["key"] = 2
let index = dict.index(forKey: "key")
// index為nil報錯
dict.remove(at: index!)
// 有則改壕曼,無則加
dict.updateValue("value2", forKey: "key2")
dict.removeValue(forKey: "key2")
dict.removeAll()
for value in dict.values {
print(value)
}
for (key ,value) in dict {
print(key, value)
}
// 類擴(kuò)展---字典的相+
extension Dictionary {
static func +(dic : Dictionary, dic2 : Dictionary) -> Dictionary
{
var result = dic
for (key , value) in dic2 {
result[key] = value
}
return result
}
}
元組
// 元組類型 (name: String, Int, score: Int)苏研, 可以作為返回值
let yz = (name : "zhangsan", _ : 18, score : 2)
yz.0
yz.name
yz.score
let(name, age, score) = ("zhangsan", 2, 2)
可選類型
1. 非可選類型 (使用的時候必須有值)
let sum : Int
2. 可選類型 (才能賦值為nil)
Swift中的nil
!= OC中的nil
,Swift種的nil
就是一個特殊含義的字符窝稿,表示沒有值
// let sum0 : Int?
// let sum0 : Optional<Int> = 2
let sum1 : Int!
sum = nil
// sum0 (Int?)需要解包才能使用
// sum1 (Int!)賦值后可以直接使用楣富,不用解包
3. 四種方式使用可選類型的值
1. 判斷 + 直接解包
if sum != nil {
sum!
}
2. 可選綁定
if let tmp = sum {
tmp
}
3. guard守護(hù)
func funcl(tmp : Int?) {
guard let test = tmp else {
return
}
test
}
4. 空合運(yùn)算符
// 如果sum == nil,那么取 ?伴榔? 后面的值
// 如果 sum != nil, 取 sum! 強(qiáng)制解包后的值
let tmp2 = sum ?? 0
類型轉(zhuǎn)換
var a = 8.8
a is Int
a is Double
let str = "123"
str as NSString
str as Any
// as! 代表纹蝴,肯定可以轉(zhuǎn)換成功,轉(zhuǎn)換的結(jié)果踪少,是非可選 不能為nil
// as? 代表塘安,系統(tǒng)嘗試幫你進(jìn)行轉(zhuǎn)換,轉(zhuǎn)失敗了援奢,就為nil
函數(shù)
1. 函數(shù)的四種類型
1. 無參數(shù)兼犯,無返回值
func func1() {
}
func func2() -> Void {
}
func func3() -> () {
}
2. 無參數(shù),有返回值
func func1() {
}
func func2() -> Int {
return 0
}
// 返回元組
func func3() -> (Int, String) {
return (1, "123")
}
3. 有參數(shù)集漾,無返回值
func func1(age : Int) {
}
4. 有參數(shù)切黔,有返回值
func func3(age : Int) -> (Int, String) {
return (1, "123")
}
函數(shù)其他注意
1. 省略第一個外部參數(shù)的名字
// 省略第一個內(nèi)部參數(shù)(函數(shù)內(nèi)部可以使用的參數(shù))
// 從swift3.0開始默認(rèn)第一個參數(shù)既是外部參數(shù)(函數(shù)調(diào)用時可以看到的參數(shù))也是內(nèi)部參數(shù)
func func2(_ name : Int, name2 : Int) -> Int {
return 0
}
2. 設(shè)置參數(shù)默認(rèn)值
// 設(shè)置默認(rèn)值,會生成幾種組合(帶不帶第二個參數(shù)的)
func func2(name : Int, name2 : Int = 1) -> Int {
return 0
}
3. 設(shè)置可變參數(shù)
// 可變參數(shù) 類型...
// 函數(shù)內(nèi)部具篇,把這個參數(shù)纬霞,當(dāng)做數(shù)組來處理
// 函數(shù)外部,直接可以傳遞多個值驱显,用逗號隔開
func addNum(nums : Int...) -> Int {
var result = 0
for num in nums {
result += num
}
return result
}
addNum(nums: 1, 2, 3)
4. 修改內(nèi)部參數(shù)的值
// 默認(rèn)不能修改內(nèi)部參數(shù)的值
func change(num : Int) {
// num 為常亮诗芜,不能修改
var num = num
num = 3
}
let a = 0
change(num: a)
5. 設(shè)置參數(shù)為地址傳遞
// inout設(shè)置第一個參數(shù)為地址傳遞
func func1(name : inout Int, name2 : Int) -> Int {
return 0
}
6. 函數(shù)嵌套
func test() {
func test2() {
print("sss")
}
}
7. 函數(shù)的類型
// (Int, Int) -> Int
// 函數(shù)的類型 : 參數(shù)類型 和返回值類型
func add(num : Int, num2 : Int) -> Int{
return num + num2
}
// (Int, Int) -> Int
// 函數(shù)的類型 : 參數(shù)類型 和返回值類型
func jian(num : Int, num2 : Int) -> Int{
return num - num2
}
func exec(n1 : Int, n2 : Int, fun : (Int, Int) -> Int) {
let result = fun(n1 ,n2)
print(result)
}
exec(n1: 3, n2: 2, fun: add)
exec(n1: 3, n2: 2, fun: jian)
8. 區(qū)分不同函數(shù)
func test() {
}
// 參數(shù)返回值不同
func test() -> Int {
return 0
}
// 參數(shù)類型不同
func test(age : Int) -> Int {
return 0
}
// 參數(shù)名字不同
func test(_ age : Int) -> Int {
return 0
}
// 參數(shù)名字不同
func test(name : Int) -> Int {
return 0
}
枚舉
// 在swift里面,枚舉類型埃疫,默認(rèn)情況伏恐,不表示任何類型,就是一個標(biāo)識
// 類型首字母大寫栓霜,元素小寫
enum Direction {
case east
case west
}
enum Direction2 {
case east, west
}
enum Direction3 : Int {
case east = 1
case west = 3
case north // Direction3.north.rawValue = 4 會自己累加
case south
}
// 只有后邊指定類型才能敲出rawValue
// Direction4.left.rawValue 取出的值就是指定的類型
enum Direction4 : String {
case left = "left"
case right = "right"
case top
case down
func func1() {
print("wwwww")
}
static func func2() {
print("rrrr")
}
}
let rv = Direction3.north.rawValue
let rv2 = Direction3(rawValue: 1)
let rv3 = Direction4(rawValue: "left")
func test(path : Direction4) {
if path == .left {
print(path.rawValue)
}
}
結(jié)構(gòu)體
1. 結(jié)構(gòu)體基本使用
// 類型方法 static func
// 實(shí)例方法 func
// 無論是枚舉翠桦,還是結(jié)構(gòu)體,都可以寫方法
struct Point {
// 實(shí)例屬性
var x : Double
var y : Double
// 實(shí)例方法
func distance() -> Double {
return x - y
}
mutating func distance2() -> Double {
x += 2 // 修改實(shí)例屬性 方法要加mutating
print(Point.z) // 訪問類型屬性
return x - y
}
// 類型屬性
static var z : Double = 0 // 需要初始化
// 類型方法
static func dis() {
// print(x) 不能直接訪問x
print(z)
print(Point.z)
}
}
2. 結(jié)構(gòu)體擴(kuò)充構(gòu)造函數(shù)
struct Point {
// 實(shí)例屬性
var x : Double
var y : Double
var z : Double?
// 自定義 “構(gòu)造函數(shù)” 叙淌!= 普通函數(shù)
// 不加func,必須使用init作為名稱
// 在構(gòu)造函數(shù)內(nèi)部秤掌,必須要保證,所有的非可選屬性鹰霍,必須有值
// 如果我們自定義了構(gòu)造函數(shù)闻鉴,那么系統(tǒng)生成的逐一構(gòu)造器,就沒有了
init(x : Double, y : Double) {
self.x = x
self.y = y
}
init(x : Double, y : Double, z : Double) {
self.x = x
self.y = y
self.z = z
}
}
類
1. 類的聲明初始化
// swift類茂洒,是可以不繼承父類孟岛,那它本身就是rootClass
// 可以寫屬性和方法
// 屬性:實(shí)例屬性,類型屬性
// 方法:實(shí)例方法,類型方法
// 類渠羞,默認(rèn)情況下斤贰,不會生成逐一構(gòu)造器(目的,保證所有的非可選屬性有值)
// 默認(rèn)情況下次询,不能保證荧恍,所有的非可選屬性有值
// 一個實(shí)例對象被創(chuàng)建好以后,必須保證里面所有的非可選屬性有值
// 方案1:在構(gòu)造函數(shù)中入手屯吊,給非可選屬性初始化
// 方案2:把非可選 -> 可選
// 方案3:給非可選的屬性賦值默認(rèn)值
class Person {
var age : Int
init(age : Int) {
// 為了不與age參數(shù)沖突才使用self
self.age = age
}
init() {
age = 2
}
}
// 不會生成逐一構(gòu)造器
let p = Person()
let p2 = Person(age: 3)
2. 類的屬性和方法
class Person {
// 實(shí)例屬性 - 存儲屬性(可以用來存儲數(shù)值的屬性)
var score = 1
var score2 : Int = 0 {
willSet {
score2 // old
newValue // new
}
// willSet(changeName) {
// score2 // old
// changeName // new
// }
didSet {
score2 // new
oldValue // old
}
}
// 實(shí)例屬性 - 計算屬性(并不是直接用來存儲數(shù)值的送巡,它是通過某些計算得來的數(shù)值)
var b : Int {
get {
return score + score2
}
set {
newValue
}
}
// 類型屬性
static var c = 1
static var d : Int?
// 實(shí)例方法
func func1() {
self.score += 1
}
// 類型方法 - 不可以被子類重寫override
static func func2() {
print("rrrr", c)
}
// 類型方法 - 可以被子類重寫(結(jié)構(gòu)體不能用class聲明方法)
class func func3() {
print("sss")
}
// 結(jié)構(gòu)體不能使用deinit析構(gòu)函數(shù)
// 析構(gòu)函數(shù)只能被定義在class類中,不能在extension中
deinit {
print("類死了")
}
}
3. 類的繼承之KVC使用
class Person : NSObject {
var age : Int = 0
var name : String = ""
init(dic : [String : Any]) {
// KVC實(shí)現(xiàn)之前盒卸,必須調(diào)用父類的init方法初始化
super.init()
setValuesForKeys(dic)
}
}
let dic : [String : Any] = ["name" : "zhangsan", "age" : 33]
let stu = Person(dic: dic)
4. 類的循環(huán)引用
class Person {
var dog : Dog?
deinit {
print("人掛了")
}
}
class Dog {
// 使用weak來避免循環(huán)引用 (unowned也可以)
weak var master : Person?
deinit {
print("??掛了")
}
}
var p : Person? = Person()
var d : Dog? = Dog()
p?.dog = d
d?.master = p
p = nil
d = nil
5. 結(jié)構(gòu)體和類的區(qū)別
- 結(jié)構(gòu)體有逐一構(gòu)造器骗爆,類沒有
- 結(jié)構(gòu)體是值類型,類是引用類型
- 結(jié)構(gòu)體不能繼承(意味著沒有多態(tài))
6. OC中使用Swift的類和結(jié)構(gòu)體
- OC與Swift混編蔽介,Swift中的函數(shù)名要符合OC的規(guī)范摘投,重載的方法用
@objc
指定名字,避免沖突 - 如果是類虹蓄,必須要繼承自
NSObject
犀呼,而且用public
關(guān)鍵字對類、方法薇组、屬性等進(jìn)行修飾 - 如果是協(xié)議最好繼承自
NSObjectProtocol
(也就對應(yīng)OC中的基協(xié)議)圆凰,用標(biāo)識符@objc
,而且聲明為public
-
Build Settings
搜索-Swift
体箕,找到Objective-C Generated Interface Header Name
里面的.h文件即為OC調(diào)用時,要包含的頭文件#import "XXX-Swift.h"
public class Person : NSObject {
public var name : String = ""
public func getAge() {
print("hello age")
}
}
@objc
public protocol work : NSObjectProtocol{
func goWork()
}
7. Swift中調(diào)用OC
- Swift項目創(chuàng)建OC文件時回生成.h橋接文件挑童,可以在
Build Settings
的Objective-C Bridging Header
中找到累铅,也可以自己創(chuàng)建.h文件,路徑跟系統(tǒng)生成的一致 - 在.h文件包含對應(yīng)的OC頭文件
三大特性
類的三大特性:封裝站叼、繼承娃兽、多態(tài)
class Test : NSObject {
// 類繼承NSObject后,下面兩個方法會報錯尽楔,說是轉(zhuǎn)換到OC以后兩個方法有沖突
func chongzai(a : Int) {
}
func chongzai(a : Double) {
}
}
解決辦法:
public class Test : NSObject {
public func chongzai(a : Int) {
}
// 通過此標(biāo)識投储,自定義生成的方法名,解決重復(fù)沖突
@objc(chongzai:)
public func chongzai(a : Double) {
}
}
// 項目名稱為app阔馋,彈框選擇的是不橋接
// Build Settings搜索-Swift玛荞,找到 Objective-C Generated Interface Header Name 里面的.h文件即為要包含的頭文件
#import "app-Swift.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Test *t = [[Test alloc] init];
[t chongzaiWithA:(NSInteger)];
}
可選鏈
class Person {
var dog : Dog?
}
class Dog {
var name : String = "wangcai"
var toy : Toy?
}
class Toy {
var price : Double = 0.0
}
let p = Person()
// 如果可選鏈的結(jié)果是nil,就代表鏈條中間至少有一個環(huán)節(jié)斷了
// () == Void != nil
p.dog?.toy?.price
協(xié)議
1.協(xié)議的基本使用
protocol work {
func run()
}
// 枚舉也可以遵循協(xié)議
enum Direction : work {
case left
case right
// 實(shí)例方法
func run() {
print("Direction run")
}
}
Direction.left.run()
// 協(xié)議可以繼承呕寝,這里不叫遵循勋眯,遵循work協(xié)議是要實(shí)現(xiàn)函數(shù)的
protocol work2 : NSObjectProtocol{
func run2()
}
// 如果遵循了協(xié)議,要求,必須實(shí)現(xiàn)協(xié)議里的所有方法
// 同時繼承 + 遵循協(xié)議客蹋,不支持多繼承
// NSObject 實(shí)現(xiàn)了NSObjectProtocol協(xié)議的所有方法
class Stu : NSObject, work2 {
func run2() {
print("Stu run2")
}
}
2. 協(xié)議中使用代理
-
weak
修飾類塞蹭,work : class
,輕量級 -
work : NSObjectProtocol
也可以,但是遵循work
協(xié)議的類讶坯,都要繼承要NSObject
了
protocol work : NSObjectProtocol{
func run()
}
//protocol work : class{
// func run()
//}
class Stu {
weak var delegate : work?
func run() {
print("Stu run2")
}
}
3. 協(xié)議中的可選
協(xié)議中的可選番电,僅僅是OC的特性,Swift是不支持的
解決方案:就是讓Swift協(xié)議辆琅,擁有OC特性
@objc
protocol work {
@objc optional func run()
}
class Stu : work {
func run() {
print("Stu run2")
}
}
泛型
// 泛化的類型漱办,不是某一個具體的類型, <T>中的T可以自定義名字
func exchange<T>(num1 : inout T, num2 : inout T) {
let tmp = num1
num1 = num2
num2 = tmp
}
class Person {
}
// 限制 T 必須繼承自 Person
func exchange2<T>(num1 : inout T, num2 : inout T) -> Int where T : Person {
let tmp = num1
num1 = num2
num2 = tmp
return 0
}
var a = 3
var b = 9
var p1 = Person()
var p2 = Person()
exchange(num1: &a, num2: &b)
// 參數(shù)必須繼承自 Person
exchange2(num1: &p1, num2: &p2)
閉包
閉包 == 特殊的函數(shù)
1.閉包的基本使用
// 函數(shù)
func add(num1 : Int, num2 : Int) -> Int {
return num1 + num2
}
// 簡單的閉包
// 如果閉包,參數(shù)是沒有的涎跨,可以省略洼冻,in和in前面的內(nèi)容
var bibao : ()->() = {
// ()->() in // 可以省略
}
// 帶參數(shù)的閉包
var bibao2 : (Int, Int)->(Int) = {
// (varg1, varg2) in
(varg1 : Int, varg2 : Int) in
return varg1 + varg2
}
bibao2(10, 20)
// 閉包當(dāng)做參數(shù)
func exec(n1 : Int, n2 : Int, block : (Int, Int)->(Int)) -> Int {
return block(n1, n2)
}
exec(n1: 20, n2: 30, block: add)
exec(n1: 20, n2: 30, block: bibao2)
exec(n1: 20, n2: 30, block: {
(a : Int, b : Int)->(Int) in
return a * b
})
2. 尾隨閉包和逃逸閉包
//尾隨閉包是一個書寫在函數(shù)括號之后的閉包表達(dá)式,函數(shù)支持將其作為最后一個參數(shù)調(diào)用隅很。在使用尾隨閉包時撞牢,你不用寫出它的參數(shù)標(biāo)簽(此處是bb)
// 如果一個函數(shù)的參數(shù),是一個閉包類型叔营,那么默認(rèn)情況下屋彪,是一個“非逃逸”閉包;(閉包绒尊,生命周期畜挥,是函數(shù))
func test(a : Int, bb : (Int, Int)->(Int)) {
let result = bb(a, 3)
print(result)
}
test(a: 20) { (sum1, sum2) -> (Int) in
return sum1 - sum2
}
// @escaping : 代表,這個閉包婴谱,是逃逸閉包蟹但,以后,有可能谭羔,會被其他的閉包华糖,延長生命周期(強(qiáng)引用)
func test2(bb : @escaping (Int, Int)->(Int)) {
bb(23, 3)
let queue = DispatchQueue(label: "xx")
let time = DispatchTime.now() + DispatchTimeInterval.seconds(2)
queue.asyncAfter(deadline: time) {
// 此處編譯器會提示添加 @escaping
_ = bb(10, 3)
}
}
test2 { (sum, sum2) -> (Int) in
return sum * sum2
}
3. 閉包的循環(huán)引用(4中解決方式)
class Person {
class Person {
var resultBlock : (()->())?
var age : Int = 0
func test() {
// weak 對象最后會被置為 nil,所以var
weak var weakSelf = self
resultBlock = {
print("222",weakSelf?.age)
}
resultBlock?()
}
func test2() {
resultBlock = {
[weak self] in
print(self?.age)
}
resultBlock?()
}
func test3() {
// unowned == __unsafe_unretained 最后不會置為nil瘟裸,編譯器建議為let
unowned let weakSelf = self
resultBlock = {
print(weakSelf.age)
}
resultBlock?()
}
func test4() {
resultBlock = {
[unowned self] in
print(self.age)
}
resultBlock?()
}
deinit {
print("人被釋放了")
}
}
var p : Person? = Person()
p?.test()
p = nil
懶加載
只是在第一次訪問的時候客叉,會調(diào)用相應(yīng)的函數(shù),獲取實(shí)例话告,下次即使值為
nil
兼搏,也不會再次調(diào)用相應(yīng)的函數(shù),獲取新的實(shí)例
class Dog {
var name : String = "wangcai"
init() {
print("創(chuàng)建了小狗")
}
}
// 懶加載
// 函數(shù):構(gòu)造函數(shù)沙郭,一般的函數(shù)佛呻,閉包
// = 后面可以跟的值:具體的指,構(gòu)造“函數(shù)”
// 所謂的懶加載病线,是指件相,在用的時候再扭,再通過后面的函數(shù),獲取相應(yīng)的實(shí)例
class Person {
lazy var dog : Dog = Dog()
// 這樣的懶加載可以對創(chuàng)建的對象進(jìn)行修改
lazy var dog2 : Dog = Person.getDog()
// 懶加載內(nèi)容放到閉包夜矗,最后調(diào)用閉包
lazy var dog3 : Dog = {
let d = Dog()
d.name = "dog3"
return d
}()
lazy var dog4 : Dog = {
$0.name = "dog4"
return $0
}(Dog())
static func getDog() -> Dog {
let d = Dog()
d.name = "getDog"
return d
}
}
注釋
// MARK: - ARC
// TODO: - todo
// FIXME: 解決bug
訪問權(quán)限
- Swift中的訪問控制模型基于模塊和源文件泛范、類這三個概念
- Swift訪問權(quán)限,作用于類紊撕,屬性罢荡,方法等
- Swift中的訪問級別遵循一個基本原則:不可以在某個實(shí)體中定義訪問級別更高的實(shí)體(類如果都不能訪問,里面的屬性方法就算開放了也不能訪問)
訪問修飾符
-
internal
: 在本模塊中都可以訪問对扶,(默認(rèn))区赵,子類也可以繼承 -
private
: 當(dāng)前類私有 -
fileprivate
: 在當(dāng)前源文件中可以訪問 -
public
: 跨模塊時,如果修飾類浪南,則無法繼承笼才。修飾方法,不能被override
-
open
: 跨模塊時络凿,如果修飾類骡送,可以繼承。修飾方法絮记,可以被override
方法拋出異常
// Error 就是在告訴編譯器摔踱,這個枚舉,可以充當(dāng)具體的異常值
enum FileError : Error{
case notExists
case notFormat
case notContent
}
// path 不存在 nil
// path存在怨愤,但是派敷,路徑對應(yīng)的文件格式不對 .png
func readFile(path : String) throws -> String {
// 1. 判斷文件路徑是否存在
let isExists = FileManager.default.fileExists(atPath: path)
if !isExists {
// 在這里面,拋出撰洗,出現(xiàn)問題的原因
// 如果想要成為篮愉,異常值,必須要遵循一個協(xié)議Error
throw FileError.notExists
// return
}
// 2. 讀取文件內(nèi)容
// 判定差导,如果這個構(gòu)造函數(shù)潜支,出現(xiàn)了異常,一般都是格式不正確
var content : String = ""
do {
content = try String(contentsOfFile: path)
} catch {
// 捕捉到異常柿汛,會執(zhí)行這個閉包
throw FileError.notFormat
}
if content.lengthOfBytes(using: String.Encoding.utf8) == 0 {
throw FileError.notContent
}
return content
}
Playground
1. Playground異步執(zhí)行
// Playground中的代碼會從上到下執(zhí)行,并在執(zhí)行完畢之后立即停止埠对,如果想要測試異步處理(比如網(wǎng)絡(luò)請求)
// 1. 導(dǎo)入PlaygroundSupport
// import PlaygroundSupport
// 2. 讓Playground永遠(yuǎn)執(zhí)行
//PlaygroundPage.current.needsIndefiniteExecution = true
// 3. 停止執(zhí)行
// PlaygroundPage.current.finishExecution()
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "xx")
let time = DispatchTime.now() + DispatchTimeInterval.seconds(2)
queue.asyncAfter(deadline: time) {
print("finish")
PlaygroundPage.current.finishExecution()
}
print("first")
2. MarkDown語法
從Xcode右邊文件屬性络断,選中Render Documentation看渲染效果
//: [Previous](@previous)
//: [Next](@next)
//PageName為頁名字不能有空格
//: [Go to AnyPage](PageName)
3. TimeLine使用
點(diǎn)擊右上角雙環(huán)(Show the Assistant editor),在代碼中做的動畫可以在TimeLine中預(yù)覽
4. Playground的Sources目錄
- 放到Sources目錄下的源文件會被編譯成模塊(module)并自動導(dǎo)入到Playground中,只會編譯一次
- 使用注意:需要使用
public
關(guān)鍵字修飾資源文建中项玛,需要暴露給外界的內(nèi)容