Swift3.0学习(三)

1、协议的基本使用

  • 协议可以继承
  • 类、结构体和枚举都可以遵循协议
  • 如果遵循了协议,则必须实现协议里所有的方法

2、协议的代理使用

轻量级的时候只需加class

protocol Work: class {
    func work()
}
class Person {
    //只有Work继承于work或者NSObjectProtocol,这里才能用weak
    weak var delegate: Work?
    
    func doWork() {
        // 让别人"打印机" 去打印
        delegate?.work()
    }
}

更全的时候加NSObjectProtocol

protocol Work: NSObjectProtocol {
    func work()
}
class ColorP: NSObject, Work {
    func work() {
        print("彩色打印机打印")
    }
}

3、让协议的方法可选(不用实现)

纯Swift并不提倡这么做,从契约精神上讲遵循协议就应该全部做到里面规定的内容

@objc
protocol Work {
   @objc optional func test()
}

//下面是关键字objc的另一个使用场景
class pp:NSObject{
    func test(a: Int)  {
    }
    @objc(xxx:)//告诉oc,当在oc里使用时下列方法名为xxx:
    func test(a: Double)  {        
    }
}

4、泛型

定义:不是某一种具体的类型,它的类型在传值的时候才会决定

// 函数
func exchange(num1: inout T, num2: inout T) {
    
    let temp = num1
    num1 = num2
    num2 = temp
    
}
var num1 = "10"
var num2 = "20"
//exchange(num1: &num1, num2: &num2)
exchange(num1: &num1, num2: &num2)
num1
num2
// 结构体
struct Point {
    var x: T
    var y: T
}

let p = Point(x: 10, y: 10)
p.x

let p2 = Point(x: 10.1, y: 10.3)
p2.x
// 类
class Stack {
    
    var nums: [T] = []
    
    func push(num: T) {
        nums.append(num)
    }
    
    func pop() -> T {
        return nums.removeLast()
    }
    
}

let st = Stack()
st.push(num: "10")
st.push(num: "20")
st.nums
st.pop()
st.pop()
//协议
protocol Some {
    
    // 协议里面,定义一个泛型, associatedtype
    associatedtype T
    
    func work() -> T
    func eat() -> T
    
}


class Person: Some {
    func work() -> Person {
        print("人工作")
        return self
    }
    func eat() -> Person {
        print("人吃饭")
        return self
    }
    
}

let p22 = Person()
p22.work().eat().work().eat().eat().eat().eat()


class Dog: Some {
    func work() -> Dog {
        print("工作")
        return self
    }
    func eat() -> Dog {
        print("吃饭")
        return self
    }
    
}

let d = Dog()
d.eat().work().eat().eat().eat().eat()

class Stu : Person {
    
    
}

func test2(a: T) where T: Person {
    
}

test2(a: Person())

where给泛型加限制条件

func test2(a: T) where T: Person {
    //这里的意思是泛型T必须是继承于Person类型
}

5、闭包的基本使用

var addBlock: (Int, Int) -> (Int) = {
    (a:Int,b:Int) -> (Int) in
    
    return a + b
    
}
addBlock(12, 12)

如果闭包参数是空,可以省略in和in前面的内容

var simpleBibao: () -> (Int) = {
    print("test")
    return 10
}

6、三种闭包

  • 参数闭包
  • 尾随闭包:当设计一个函数,其内部需要接收闭包,一定要注意尽量把闭包类型的参数放最后
  • 逃逸闭包:如果一个函数的参数,是一个闭包类型,那么默认情况下,是一个“非逃逸”的闭包(闭包,生命周期,是函数)

7、闭包循环的问题

OC中的循环问题

定义block的时候,用setXXBlock能比较方便的打出格式

  • __weak和__unsafe_unretained的区别:前者释放后会置为nil而后者不会
  • __strong的使用:当一个Ablock里面嵌套另一个耗时操作的Bblock,在Bblock里需要使用self,为了防止使用时self已经被释放为空的情况,这时候会使用关键字__strong
    __weak typeof(self)weakSelf = self;
        [self setBlock:^(int a) {
            //
            __strong typeof(self)strongSelf = weakSelf;
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 *   NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                //
                [strongSelf xxx];
            });
        }];
    

Swift中的使用

class Person {
    
    var block: (()->())?
    
    func test() {
        block = {
            [weak self] in
            self
            print("test")
        }
    }
    
    deinit {
        print("Person释放了")
    }
    
}

var p: Person? = Person()
p?.test()
p = nil

8、懒加载的使用

使用关键字lazy

class Dog {
    var age: Int = 0
}

class Person {
    //冒号后面一般跟具体的值、构造函数或者闭包
    lazy var name: Dog =  {
        //       () -> Dog in
        print("test")
        return Dog()   
    }()
}

注:与OC不同的是Swift中懒加载置为nil以后不能再重复加载了

9、常见注释的写法

Swift3.0学习(三)_第1张图片

另外,Swift里还可以开启注释(让FIXME像感叹号那样有提示便于查找),开启方法:把下面这段代码复制到BuildPhases→NewRunScriptPhases

TAGS="TODO:|FIXME:"
echo "searching ${SRCROOT} for ${TAGS}"
find "${SRCROOT}" \( -name "*.swift" \) -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($TAGS).*\$" | perl -p -e "s/($TAGS)/ warning: \$1/"

10、访问权限问题

OC
默认是@protected

OC中通常认为只有成员变量会存在访问权限问题,属性和方法都不存在;成员变量用箭头(->)访问;一旦修饰,该成员变量后面的都被修饰了,之道遇到下一个修饰

Swift

  • internal:默认的,类似OC中的protected,当前模块内都可以访问
  • private:私有
  • fileprivate:在当前源文件中可以访问(当前源文件是指当前这一个xx.swift文件,当前模块是指当前这个Target,Swift中同一个模块不需要import)
    -public:修饰的对象可以跨模块,修饰类时不能继承,修饰方法时不能重写
  • open:修饰的对象可以跨模块,修饰类时可以继承,修饰方法时可以重写

与OC不同的一个细节是,这些关键字都只会修饰接下来的一个对象,而不是后面所有的

11、异常的抛出和处理

格式与OC类似

// 捕捉, 并且处理
do {
    let content = try readFile(path: path)
}catch {
    switch error {
    case FileError.NoPath:
        print("路径不存在")
    case FileError.UnAvailable:
        print("格式错误")
    case FileError.NoContent:
        print("没有内容")
    default:
        print("不知道")
    }
}


// try? 处理异常, 就代表, 告诉编译器, 我知道有可能会出现错误, 你帮我自动处理就好, 如果错误, 就直接给我nil < 如果没有错误, 就给我答案
//let content = try? readFile(path: path)

// try!, 代表, 我保证, 绝壁没有任何错误, 告诉编译器, 只负责给我值, 保证是有值得, 放心拿
let content = try! readFile(path: path)

12、Swift调用OC

使用场景:可以调用OC写的三方框架

在Swift项目中创建OC文件时会提示如下图


Swift3.0学习(三)_第2张图片

注:这个桥接文件只对Swift引用OC有效

13、OC调用Swift

OC项目里调用Swift就没这么方便了,这时候同样会出现上图这个窗口,但是不要点Create,我们需要自己去创建(因为Swift文件没有单独的声明和实现文件,且是整个是一个模块)


Swift3.0学习(三)_第3张图片

14、Playground的高级应用

  1. 资源共享
  2. 异步执行
  3. 多页面
  4. 动画时间轴
Swift3.0学习(三)_第4张图片

你可能感兴趣的:(Swift3.0学习(三))