SWIFT开发tips

最近看了一点关于swift的书籍,记录一些知识点。都是我自己的理解,可能会有些不准确的地方,请指出来,一起学习,感激不尽。

swift 3.1官方介绍地址

Swift的官方文档:

1.Assert: 断言

在Swift中,通过assert实现断言,assert可以帮助开发者比较容易的发现和定位错误,断言断定条件是true。通过声明一个断言来确保某个必要的条件是满足的,以便继续执行接下来的代码。如果条件满足了,那么代码像往常一样执行,如果不满足了,代码就停止执行了,应用也随之停下来了。 只是查找问题,在只有TRUE的情况才可以执行的代码位置 加上断言。。
断言的另一个优点是它是一个开发时的特性,只有在 Debug 编译的时候有效,而在运行时是不被编译执行的,因此断言并不会消耗运行时的性能。这些特点使得断言成为面向程序员的在调试开发阶段非常合适的调试判断,而在代码发布的时候,我们也不需要刻意去将这些断言手动清理掉,非常方便。

2.fatalError

fatalError 和断言有点类似。fatalError 是抛出一个异常,让程序结束。
fatalError的作用就是产生一个致命的错误,来终止程序。和断言的区别就是:在release环境下依然可以使用。

使用场景举例:父类有一个方法,要求子类必须实现,这时候就可以在父类方法中写上这个fatalError, 当子类没有实现这个方法,但是直接调用了这个方法时,就直接停止程序。

举个栗子:
我们定义了一个方法,但是不想让别人调用,但是又不得不暴露出来,这时候就可以使用fatalError了。

func methodMustBeImplementedInSubClass() {
        fatalError("这个方法必须在子类中被重写")
    }
//子类方法1
class subClass: CategaryViewController {
    override func methodMustBeImplementedInSubClass() {
        print("实现了父类的方法")
    }
}

//子类方法1
class subClass1: CategaryViewController {
    func someMethod() -> Void {
        print("myself method,没有实现父类的方法")
    }
}
//调用方法 
 let subclass = subClass()
 subclass.methodMustBeImplementedInSubClass()
        
 let subclass1 = subClass1()
//这里程序就会崩溃,因为没有重写父类方法。。fatalError触发了。。
 subclass1.methodMustBeImplementedInSubClass()

3.procotol 代理。swift里procotol 方法默认都要实现。

代理的写法 注意:swift代理的方法都必须要实现,不然会报错。
// 对于需要结构体和枚举遵守的协议方法需要在前面添加mutating
参见:UITableViewDataSource代理,当你继承了这个代理,但是还没有实现其两个代理方法,程序就会报错;当你实现了cell和行数两个代理方法就ok了。
直接类似OC那样写是不可以的,没有类似weak属性,因为swift的协议可以给除了可以被class遵守,enum和struct也可以遵守。
1、在代理前面加@objc,但是这样可能会出现兼容OC的问题,在前面加上@objc 方法名前加:@objc optional,没加的默认都是要必须实现的。带有@objc关键字的协议只能被OC类,或者带有@objc关键字的类遵守,结构体和枚举都不能遵守.

2、在协议后面加上:class,限定整个procotol只能有class实现。 枚举和结构体不可以实现。。

protocol CustomCellDelegate: class {    
  required func method()
}

//另外一种可选实现方案:swift里的协议可选方法实现,使用扩展的方式

//定义个协议
protocol OptionalProtocool {   
//默认三个协议方法是都要实现的 
func opotionalMetod()    
func necessaryMethod()    
func anotherOptionalMetod()
}
//扩展协议 将父协议的两个方法已经实现,所以遵守协议的类,可以不实现这个协议已经实现的方法
extension OptionalProtocool {   
 func optionalMethod() -> Void {        
print("optionalMethod")   
 }       
func anotherOptionalMethod() -> Void {      
  print("anotherOpthionalMethod")    
}
}
//类遵守了协议
class Myclass: OptionalProtocool {   
//必须要实现的协议方法
 func necessaryMethod() {        
 print("necessaryMethod")   
 }       
//可选实现的协议方法 ,anotherOptionalMethod()这个方法没实现没有关系,因为已经在协议扩展里实现了。
func opotionalMetod() {        
print("optionalMehod")  
 }
}

4.继承:

重写父类方法、属性需要在前面加override关键字
如果不想被子类重写,父类定义方法要在前面加上 final 关键字
子类也可以再次被继承,子类可以直接访问父类的属性、方法。

5.注释

xcode8 swift里有注释方法 统一为:///
再给方法等添加注释的时候,默认快捷键:cmd+alt+/ ,会直接生成注释代码 ;在调用方法时候,安装alt+点击,就能显示出注释的内容。

6.关于打印print方法

在swift里打印完成自动换行,假如不想换行,就要在最后一个参数那里设置为nil。
print(“print something ”, nil )
如果你想在打印一段文本中间就换行,只需添加\n即可:
eg: print(“123\n456”)

7.単例

class singleClass {    
static let single = singleClass()    
private init() {}
}

8.输出格式化

let b = 1.34343434
extension Double {    
 func formart(_ f: String) -> String {       
  return String(format: "%\(f)f",self)    
 }
}
//保留两位小数
let f = ".2"print("double: \(b.formart(f))")

9.数组遍历

//时候和OC数组遍历说再见了
let arr: Array = [1,2,3,4,5]
var result = 0
for (idx, num) in arr.enumerated() {    
result += num    
if idx ==2 
  {    break    }
}
print(result)  //1+2+3=6;

10.延时执行

//2s后执行某一个方法 几秒必须要加DispatchTime.now() + (n)s
let time: TimeInterval = 2.0
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time) {
    print("2s late print") 
}

11.初始化顺序
与OC不同,swift的初始化方法需要保证类型的所有属性都被初始化。
保证当前子类实例的成员初始化完成之后才能调用父类的初始化方法。
init 构造器:如果子类必须要实现父类的构造器,父类要用require修饰init。可以自定义构造器,如果没有实现构造器,系统默认实现。

class Animals {
    var name: String
    init() {
        name = "cat"
    }
}

class Tigger : Animals {
    let power: Int
    override init() {
        power = 100
        //如果我们不用改变name的话,可以不用调用super.init(),因为这是初始化最后了,swift替我们完成了
//        super.init()
//        name = "tigger"
    }
}

析构器:deinit 相当于OC中的dealloc。父类实现了析构器,子类也会继承下来,所有类簇只能有一个析构器。

12.属性观察 willset 和 didset

//属性观察  willset 和 didset
class MyClass {
let oneYearSeconds: TimeInterval = 365*24*60*60
var date:NSDate {
        willSet {
            let d = date
            print("日期即将从\(d)shezhidao \(newValue)")
        }
        didSet {
            //我们可以在这里做一些自己需要的事情,如果是不满足,可以将date设置为你想要的那个值
            if(date.timeIntervalSinceNow > oneYearSeconds)
            {
                print”设定的时间太晚了,早点吧”
                date = NSDate().addingTimeInterval(oneeYearSeconds)
             }
            print("日期已经从\(oldValue)设置至 \(date)")
        }
    }

 init() {
        date = NSDate()
    }
}

13.改写log打印方法

    //log的打印方式
    func printLog<T>(_ message: T,
                  file: String = #file,
                  method: String = #function,
                  line: Int = #line)
    {
        #if DEBUG
            print("类:\((file as NSString).lastPathComponent), 第\(line)行, 方法:\(method), \n内容: \(message)")
        #endif
    }

14.闭包

类似OC 暴露一个block 怎么实现??传一个闭包进来,参数和返回值一样就好了。 闭包可以看做OC的block。extension 相当于OC里的类别,但是比类别更强大、好写。
unowned 无主引用和 weak 弱引用。

15.错误处理

// 处理错误的几种方式: 1. 把错误传递给调用函数,然后使用do-catch语句处理错误
// 2. 将错误作为可选类型处理
// 3. 使用断言处理

// throwing函数: 在参数列表后面加throws,表示可以抛出错误
如果有返回类型,throws需要写在(->)前面, throw语句会立刻退出当前方法,相当于return

let throwClass = ThrowClass()
throwClass.num = 4

do {
    try throwClass.throwFunc()
}catch CustomErrorType.errorReason1 {   // 根据返回错误类型,执行这个{}
    print("errorReason1")               // errorReason1
}catch CustomErrorType.errorReason2 {
    print("errorReason2")
}catch {                                // catch没有指定类型,那么可以匹配任何错误
    print("errorReason3")
}
  1. defer语句
    defer语句在异常抛出前,通常需要做一些操作,比如关闭文件,手动释放内存等,这些就可以在defer语句中执行
    // defer语句会在return,break,以及错误抛出之前执行
    // defer语句可以有多个
    // defer语句必须要在throw语句前面才能执行

17.扩展 ——类似OC的分类.可以为已有的类 结构体 枚举或者协议类型添加新功能
// swift中可以扩展的功能: 1. 为已有类型扩展计算型实例属性和计算型类型属性
// 2. 为已有类型添加新的便利构造器
// 3. 为已有类型添加新的实例方法和类型方法
// 4. 为已有类型添加新下标
// 5. 为已有的类 结构体 枚举添加新的嵌套类型

// 扩展语法
class SomeClass {                       // 定义一个要扩展的SomeClass类
}
extension SomeClass: someProtocol {     // 在类名前面添加extension关键字,冒号后面写协议名
    // 扩展功能,协议实现写在这里
}

18.Api限定版本使用

//下面这个属性是 标明:只有在iOS10以后才可以用
@available(iOS 10, *) var animate : UIViewPropertyAnimator!
或者
@available(iOS 10, *)
var animate : UIViewPropertyAnimator!

 //代码里判断哪个版本
if #available(iOS 10, *) {}

未完 暂时先写这么多,下篇继续。。。

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

推荐阅读更多精彩内容

  • Swift2.0 1.defer译为延缓、推迟之意类似栈 注意作用域,其次是调用顺序——即一个作用域结束(注意),...
    zeqinjie阅读 3,367评论 0 50
  • 问题 1)柯里化,通过柯里化,改造target-action,因为selector只能使用字符串,在编译时无法发现...
    lanjing阅读 3,483评论 3 19
  • 1、范型范型所解决的问题 函数、方法、类型:类,结构体,枚举,元组类型,协议参数,返回值,成员函数参数,成员属性类...
    我是小胡胡分胡阅读 816评论 0 1
  • 常量与变量使用let来声明常量,使用var来声明变量。声明的同时赋值的话,编译器会自动推断类型。值永远不会被隐式转...
    莫_名阅读 435评论 0 1
  • 今天下班后赶回宿舍,立马做完今天应该做的事,去和许久未见的朋友聊聊天。 我们五个好朋友是在学校的广播台认识的,大家...
    陈溺阅读 272评论 0 3