Swift 3.0基础语法

Swift笔记

Any AnyObject NSObject

Int Double String struct都是结构体

  1. Any : 一个协议声明
  2. AnyObject : 一个具体的协议,协议里面没有内容,默认情况下,所有的类,都遵循了这个协议
  3. NSObjectNSObject

条件判断

swift中没有非零即真和零为假的说法,只有严格的Bool(true/false)

1. if的使用

let a = 1
if a == 1 {
    print("test")
}else if  a == 2{
    print("sss")
}else {
    print("wwqw")
}

2. 三目运算符

a == 1 ? print("first") : print("hello")

3. guard

  1. guard条件成立,继续往下走,不成立执行else里面的语句
  2. 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与基本数据

// 必须要加default, 但是有些情况可以不加,例如枚举的各个情况都判断过了
// 判断类型 可以是浮点型,String,对象。
let a = 11

switch a {
case 1, 11:
    print("1, 11")
    fallthrough // 会有穿透效果,如果这个case为true,也执行下个case的内容
case 2:
    print("2")
default:
    print("不知道")
}

2. switch与区间

let score = 10.0
switch score {
case 0 ..< 60:
    print("不及格")
case 60 ..< 90:
    print("及格")
case 90 ..< 100:
    print("优秀")
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,因为各个情况都已经判断过,default也不会执行
//    print("ss")
}

4. switch与元组

let point = (10, 25)
switch point {
case (0, 0):
    print("坐标在原点")
case (1...10, 10...20): // 可以在元组中再加上区间
    print("坐标的X和Y在1~10之间")
case (_, 0): // X可以是任意数
    print("坐标的X在X轴上")
case (var x, var y): // x,y来接收参数 一定为true
    print("333")
case var(x,y): where x > y // x,y来接收参数 x>y则一定为true
    print("1111")
default:
    print("Other")
}

循环

1. for循环

for i in 0 ..< 10 {
    print(i)
}

// _代表忽略的意思
for _ in 0 ..< 10 {
    print("test")
}

2. while循环

1. while循环

var i = 10
while i > 0 {
    i -= 1
    print(i)
}

2. repeat~while循环

// 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")

// 转为OC的NSString处理
let str3 = (str2 as NSString).substring(to: 2)

数组

// 数组的声明和初始化
let arr1 = [2]
var arr2 : [Any] = [1, 2, "ii", 11, "ss", "w"]
let arr3 = [1, 1.1, "ss"] as [Any]

// 相同类型的数组可以直接相加
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)

// 操作数组的区间
let rang2 = 0 ..< 2
arr2.removeSubrange(0 ..< 2)

// 获取数组最大最小
var arr = [1, 2]
arr.min()
arr.max()
var arr4 = ["a", "3.3"]
// 比的ASCII码
arr4.min()
arr4.max()

// 数组的遍历
for i in 0 ..< arr2.count {
    print(arr2[i])
}

// 利用元组获取数组的 角标+ 值
for (key ,value) in arr2.enumerated() {
    print(key, value)
}

for i in arr2[0...2] {
    print(i)
}

// 转为OC数组的遍历
(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)
}

// 类扩展---字典的相+
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守护

func funcl(tmp : Int?) {
    guard let test = tmp else {
        return
    }
    test
}

4. 空合运算符

// 如果sum == nil,那么取 ?? 后面的值
// 如果 sum != nil, 取 sum! 强制解包后的值 
let tmp2 = sum ?? 0

类型转换

var a = 8.8
a is Int
a is Double


let str = "123"
str as NSString
str as Any

// as! 代表,肯定可以转换成功,转换的结果,是非可选 不能为nil
// as? 代表,系统尝试帮你进行转换,转失败了,就为nil

函数

1. 函数的四种类型

1. 无参数,无返回值

func func1() {
    
}
func func2() -> Void {
    
}
func func3() -> () {
    
}

2. 无参数,有返回值

func func1() {
    
}
func func2() -> Int {
    return 0
    
}
// 返回元组
func func3() -> (Int, String) {
    return (1, "123")
}

3. 有参数,无返回值

func func1(age : Int) {
    
}

4. 有参数,有返回值

func func3(age : Int) -> (Int, String) {
    return (1, "123")
}

函数其他注意

1. 省略第一个外部参数的名字

// 省略第一个内部参数(函数内部可以使用的参数)
// 从swift3.0开始默认第一个参数既是外部参数(函数调用时可以看到的参数)也是内部参数
func func2(_ name : Int, name2 : Int) -> Int {
    return 0
}

2. 设置参数默认值

// 设置默认值,会生成几种组合(带不带第二个参数的)
func func2(name : Int, name2 : Int = 1) -> Int {
    return 0
}

3. 设置可变参数

 // 可变参数  类型...
 // 函数内部,把这个参数,当做数组来处理
 // 函数外部,直接可以传递多个值,用逗号隔开
func addNum(nums : Int...) -> Int {
    var result = 0
    for num in nums {
        result += num
    }
    return result
}
addNum(nums: 1, 2, 3)

4. 修改内部参数的值

// 默认不能修改内部参数的值
func change(num : Int) {
    // num 为常亮,不能修改
    var num = num
    num = 3
}
let a = 0
change(num: a)

5. 设置参数为地址传递

 // inout设置第一个参数为地址传递
func func1(name : inout Int, name2 : Int) -> Int {
    return 0
}

6. 函数嵌套

func test() {
    func test2() {
        print("sss")
    }
}

7. 函数的类型

// (Int, Int) -> Int
// 函数的类型 : 参数类型 和返回值类型
func add(num : Int, num2 : Int)  -> Int{
    return num + num2
}

// (Int, Int) -> Int
// 函数的类型 : 参数类型 和返回值类型
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. 区分不同函数

func test() {   
}
// 参数返回值不同
func test() -> Int {
    return 0
}
// 参数类型不同
func test(age : Int) -> Int {
    return 0
}
// 参数名字不同
func test(_ age : Int) -> Int {
    return 0
}
// 参数名字不同
func test(name : Int) -> Int {
    return 0
}

枚举

// 在swift里面,枚举类型,默认情况,不表示任何类型,就是一个标识
// 类型首字母大写,元素小写
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)
    }
}

结构体

1. 结构体基本使用

// 类型方法 static func
// 实例方法 func
// 无论是枚举,还是结构体,都可以写方法
struct Point {
    // 实例属性
    var x : Double
    var y : Double
    // 实例方法
    func distance() -> Double {
        return x - y
    }

    mutating func distance2() -> Double {
        x += 2  // 修改实例属性 方法要加mutating
        print(Point.z) // 访问类型属性
        return x - y
    }
    
    // 类型属性
    static var z : Double = 0 // 需要初始化
    // 类型方法
    static func dis() {
//        print(x) 不能直接访问x
        print(z)
        print(Point.z)
    }
    
}

2. 结构体扩充构造函数

struct Point {
    // 实例属性
    var x : Double
    var y : Double
    var z : Double?
    
    // 自定义 “构造函数” != 普通函数
    // 不加func,必须使用init作为名称
    // 在构造函数内部,必须要保证,所有的非可选属性,必须有值
    // 如果我们自定义了构造函数,那么系统生成的逐一构造器,就没有了
    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
// 可以写属性和方法
// 属性:实例属性,类型属性
// 方法:实例方法,类型方法
// 类,默认情况下,不会生成逐一构造器(目的,保证所有的非可选属性有值)
// 默认情况下,不能保证,所有的非可选属性有值
// 一个实例对象被创建好以后,必须保证里面所有的非可选属性有值
// 方案1:在构造函数中入手,给非可选属性初始化
// 方案2:把非可选 -> 可选
// 方案3:给非可选的属性赋值默认值

class Person {
    var age : Int
    init(age : Int) {
    // 为了不与age参数冲突才使用self
        self.age = age
    }
    init() {
        age = 2
    }
}
// 不会生成逐一构造器
let p = Person()
let p2 = Person(age: 3)

2. 类的属性和方法

class Person {
    // 实例属性 - 存储属性(可以用来存储数值的属性)
    var score = 1
    var score2 : Int = 0  {
        willSet {
            score2 // old
            newValue // new
        }
        
        //        willSet(changeName) {
        //            score2 // old
        //            changeName // new
        //        }
        didSet {
            score2 // new
            oldValue // old
        }
    }
    // 实例属性 - 计算属性(并不是直接用来存储数值的,它是通过某些计算得来的数值)
    var b : Int {
        get {
            return score + score2
        }
        set {
            newValue
        }
    }
    // 类型属性
    static var c = 1
    static var d : Int?
    // 实例方法
    func func1() {
        self.score += 1
    }
    
    // 类型方法 - 不可以被子类重写override
    static func func2() {
        print("rrrr", c)
    }
    // 类型方法 - 可以被子类重写(结构体不能用class声明方法)
    class func func3() {
        print("sss")
    }
    // 结构体不能使用deinit析构函数
    // 析构函数只能被定义在class类中,不能在extension中
    deinit {
        print("类死了")
    }
}

3. 类的继承之KVC使用

class Person : NSObject {

    var age : Int = 0
    var name : String = ""

    init(dic : [String : Any]) {
        
        // KVC实现之前,必须调用父类的init方法初始化
        super.init()
        setValuesForKeys(dic)
    }
}

let dic : [String : Any] = ["name" : "zhangsan", "age" : 33]
let stu = Person(dic: dic)

4. 类的循环引用

class Person {
    var dog : Dog?
    deinit {
        print("人挂了")
    }
}
class Dog {
    // 使用weak来避免循环引用 (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. 结构体和类的区别

  1. 结构体有逐一构造器,类没有
  2. 结构体是值类型,类是引用类型
  3. 结构体不能继承(意味着没有多态)

6. OC中使用Swift的类和结构体

  1. OC与Swift混编,Swift中的函数名要符合OC的规范,重载的方法用@objc指定名字,避免冲突
  2. 如果是类,必须要继承自NSObject,而且用public关键字对类、方法、属性等进行修饰
  3. 如果是协议最好继承自NSObjectProtocol(也就对应OC中的基协议),用标识符@objc,而且声明为public
  4. Build Settings搜索-Swift,找到 Objective-C Generated Interface Header Name 里面的.h文件即为OC调用时,要包含的头文件 #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中调用OC

  1. Swift项目创建OC文件时回生成.h桥接文件,可以在Build SettingsObjective-C Bridging Header中找到,也可以自己创建.h文件,路径跟系统生成的一致
  2. 在.h文件包含对应的OC头文件

三大特性

类的三大特性:封装、继承、多态

 class Test : NSObject {
    // 类继承NSObject后,下面两个方法会报错,说是转换到OC以后两个方法有冲突
    func chongzai(a : Int) {
    }
    
    func chongzai(a : Double) {  
    }
}

解决办法:

public class Test : NSObject {
    public func chongzai(a : Int) {    
    }
    
    // 通过此标识,自定义生成的方法名,解决重复冲突
    @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()
// 如果可选链的结果是nil,就代表链条中间至少有一个环节断了
// () == Void != nil
p.dog?.toy?.price

协议

1.协议的基本使用

protocol work {
    func run()
}
// 枚举也可以遵循协议
enum Direction : work {
    case left
    case right
    
    // 实例方法
    func run() {
        print("Direction run")
    }
}
Direction.left.run()

// 协议可以继承,这里不叫遵循,遵循work协议是要实现函数的
protocol work2 : NSObjectProtocol{
    func run2()
}
// 如果遵循了协议,要求,必须实现协议里的所有方法
// 同时继承 + 遵循协议,不支持多继承
// NSObject 实现了NSObjectProtocol协议的所有方法
class Stu : NSObject, work2 {
    func run2() {
        print("Stu run2")
    }
}

2. 协议中使用代理

  1. weak 修饰类,work : class,轻量级
  2. work : NSObjectProtocol也可以,但是遵循work协议的类,都要继承要NSObject
protocol work : NSObjectProtocol{
    func run()
}
//protocol work : class{
//    func run()
//}

class Stu {
    weak var delegate : work?
    func run() {
        print("Stu run2")
    }
}

3. 协议中的可选

协议中的可选,仅仅是OC的特性,Swift是不支持的
解决方案:就是让Swift协议,拥有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)

// 参数必须继承自 Person
exchange2(num1: &p1, num2: &p2)

闭包

闭包 == 特殊的函数

1.闭包的基本使用

// 函数
func add(num1 : Int, num2 : Int) -> Int {
    return num1 + num2
}

// 简单的闭包
// 如果闭包,参数是没有的,可以省略,in和in前面的内容
var bibao : ()->() = {
    //    ()->() in // 可以省略
}
// 带参数的闭包
var bibao2 : (Int, Int)->(Int) = {
//    (varg1, varg2) in
    (varg1 : Int, varg2 : Int) in
    return varg1 + varg2
}

bibao2(10, 20)

// 闭包当做参数
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. 尾随闭包和逃逸闭包

//尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。在使用尾随闭包时,你不用写出它的参数标签(此处是bb)
// 如果一个函数的参数,是一个闭包类型,那么默认情况下,是一个“非逃逸”闭包;(闭包,生命周期,是函数)
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 : 代表,这个闭包,是逃逸闭包,以后,有可能,会被其他的闭包,延长生命周期(强引用)
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. 闭包的循环引用(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

懒加载

只是在第一次访问的时候,会调用相应的函数,获取实例,下次即使值为nil,也不会再次调用相应的函数,获取新的实例

class Dog {
    var name : String = "wangcai"
    init() {
        print("创建了小狗")
    }
}

// 懒加载
// 函数:构造函数,一般的函数,闭包
// = 后面可以跟的值:具体的指,构造“函数”
// 所谓的懒加载,是指,在用的时候,再通过后面的函数,获取相应的实例
class Person {
    lazy var dog : Dog = Dog()
    // 这样的懒加载可以对创建的对象进行修改
    lazy var dog2 : Dog = Person.getDog()
    // 懒加载内容放到闭包,最后调用闭包
    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

访问权限

  1. Swift中的访问控制模型基于模块和源文件、类这三个概念
  2. Swift访问权限,作用于类,属性,方法等
  3. Swift中的访问级别遵循一个基本原则:不可以在某个实体中定义访问级别更高的实体(类如果都不能访问,里面的属性方法就算开放了也不能访问)

访问修饰符

  1. internal : 在本模块中都可以访问,(默认),子类也可以继承
  2. private : 当前类私有
  3. fileprivate : 在当前源文件中可以访问
  4. public : 跨模块时,如果修饰类,则无法继承。修饰方法,不能被override
  5. open : 跨模块时,如果修饰类,可以继承。修饰方法,可以被override

方法抛出异常

// Error 就是在告诉编译器,这个枚举,可以充当具体的异常值
enum FileError : Error{
    case notExists
    case notFormat
    case notContent
}

// path 不存在 nil
// path存在,但是,路径对应的文件格式不对 .png
func readFile(path : String) throws -> String {
    // 1. 判断文件路径是否存在
    let isExists = FileManager.default.fileExists(atPath: path)
    if !isExists {
        // 在这里面,抛出,出现问题的原因
        // 如果想要成为,异常值,必须要遵循一个协议Error
        throw FileError.notExists
//        return
    }
    
    // 2. 读取文件内容
    // 判定,如果这个构造函数,出现了异常,一般都是格式不正确
    var content : String = ""
    do {
        content = try String(contentsOfFile: path)
    } catch  {
        // 捕捉到异常,会执行这个闭包
        throw FileError.notFormat
    }
    if content.lengthOfBytes(using: String.Encoding.utf8) == 0 {
        throw FileError.notContent
    }
    return content
}

Playground

1. Playground异步执行

// Playground中的代码会从上到下执行,并在执行完毕之后立即停止,如果想要测试异步处理(比如网络请求)
// 1. 导入PlaygroundSupport
// import PlaygroundSupport
// 2. 让Playground永远执行
//PlaygroundPage.current.needsIndefiniteExecution = true
// 3. 停止执行
// 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使用

点击右上角双环(Show the Assistant editor),在代码中做的动画可以在TimeLine中预览

4. Playground的Sources目录

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

推荐阅读更多精彩内容

  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young阅读 3,771评论 1 10
  • Swift 介绍 简介 Swift 语言由苹果公司在 2014 年推出,用来撰写 OS X 和 iOS 应用程序 ...
    大L君阅读 3,168评论 3 25
  • 136.泛型 泛型代码让你可以写出灵活,可重用的函数和类型,它们可以使用任何类型,受你定义的需求的约束。你可以写出...
    无沣阅读 1,452评论 0 4
  • 扩展 扩展就是向一个已有的类、结构体、枚举类型或者协议类型添加新功能。这包括在没有权限获取原始源代码的情况下扩展类...
    cht005288阅读 460评论 0 0
  • 常量与变量使用let来声明常量,使用var来声明变量。声明的同时赋值的话,编译器会自动推断类型。值永远不会被隐式转...
    莫_名阅读 435评论 0 1