• 结构体里边可以定义属性(变量,常量)和添加方法,从而扩展结构体的功能 结果体允许我们创建单一的文件,且系统自动化生成面向其他代码的外部接口 结构体总是通过被复制的方式在代码中传递,因此它的值不可改变 ...
    /*
    结构体里边可以定义属性(变量,常量)和添加方法,从而扩展结构体的功能
    结果体允许我们创建单一的文件,且系统自动化生成面向其他代码的外部接口
    结构体总是通过被复制的方式在代码中传递,因此它的值不可改变
    struct nameStruct {
    Definition 1
    Definition 2
    ……
    Definition N
    }
    */
    struct studentType
    {
        var  type1 = "A等生"
        var type2 = "B等生"
          var type3 = "C等生"
          var type4 = "D等生"
        var type5 = "努力生"
        
        
    }
    let type = studentType() //现将结构体转化成类
    print("小名是\(studentType().type1)")//当然也可以直接使用
    print("小花是\(type.type5)")

    //通过结构体实例化 并克隆一个结构体
    struct MarksStruct {
        var mark : Int //将mark初始化为int类型
        init(mark:Int) {
            self.mark=mark
        }
        
    }
    var aStruct = MarksStruct(mark:99)
    var bStuct = aStruct //此时aStruct 和bStruct 共用一样结构体
    aStruct.mark=66 //a的结构体从新赋值
    print(aStruct.mark)
    print(bStuct.mark)
    /*结果
    小名是A等生
    小花是努力生
    */


    //结构体应用

    struct markStruct{
        var mark1: Int
        var mark2: Int
        var mark3: Int
        
        init(mark1: Int, mark2: Int, mark3: Int){
            self.mark1 = mark1
            self.mark2 = mark2
            self.mark3 = mark3
        }
    }

    print("优异成绩:")
    var marks = markStruct(mark1: 100, mark2: 100, mark3:100)
    print(marks.mark1)
    print(marks.mark2)
    print(marks.mark3)

    print("糟糕成绩:")
    var fail = markStruct(mark1: 0, mark2: 2, mark3: 3)
    print(fail.mark1)
    print(fail.mark2)
    print(fail.mark3)


    /*
    优异成绩:
    100
    100
    100
    糟糕成绩:
    0
    2
    3
    */
    展开全文
  • Swift 4.0 新特性

    2017-08-15 19:37:46
    WWDC 2017 带来了很多惊喜,在这次大会上,Swift 4 也伴随着 Xcode 9 测试版来到了我们的面前,虽然正式版要8月底9月初才会公布,但很多强大的新特性正吸引我们去学习它。根据大会上已经开放的新特性,先一睹为快。...

    WWDC 2017 带来了很多惊喜,在这次大会上,Swift 4 也伴随着 Xcode 9 测试版来到了我们的面前,虽然正式版要8月底9月初才会公布,但很多强大的新特性正吸引我们去学习它。根据大会上已经开放的新特性,先一睹为快。

    体验

    Swift 4包含在Xcode 9中,您可以从Apple的开发者门户下载最新版本的Xcode 9(您必须拥有一个活跃的开发者帐户)。 每个Xcode测试版将在发布时捆绑最新的Swift 4快照。在阅读时,您会注意到[SE-xxxx]格式的链接。 这些链接将带您到相关的Swift Evolution提案。 如果您想了解有关任何主题的更多信息,请务必查看。

    版本迁移

    由于Swift 4新增了很多的新的语法特性,这些语法和思想完全区别于Swift 3及以下版本。因此,使用Swift迁移工具将为您处理大部分更改,在Xcode中,您可以导航到编辑/转换/到当前Swift语法…以启动转换工具。

    语法改进

    extension 中可以访问 private 的属性

    例如有如下代码:

    struct Date: Equatable, Comparable {
        private let secondsSinceReferenceDate: Double
        static func ==(lhs: Date, rhs: Date) -> Bool {
            return lhs.secondsSinceReferenceDate == rhs.secondsSinceReferenceDate
        }
        static func <(lhs: Date, rhs: Date) -> Bool {
            return lhs.secondsSinceReferenceDate < rhs.secondsSinceReferenceDate
        }
    }

    上面代码定义了一个 Date 结构体,并实现 Equatable 和 Comparable 协议。为了让代码更清晰,可读性更好,一般会把对协议的实现放在单独的 extension 中,这也是一种非常符合 Swift 风格的写法。

    struct Date {
        private let secondsSinceReferenceDate: Double
    }
    extension Date: Equatable {
        static func ==(lhs: Date, rhs: Date) -> Bool {
            return lhs.secondsSinceReferenceDate == rhs.secondsSinceReferenceDate
        }
    }
    extension Date: Comparable {
        static func <(lhs: Date, rhs: Date) -> Bool {
            return lhs.secondsSinceReferenceDate < rhs.secondsSinceReferenceDate
        }
    }
    

    但是在 Swift 3 中,编译就报错了,因为 extension 中无法获取到 secondsSinceReferenceDate 属性,因为它是 private 的。所以,在 Swift 3 中必须把 private 改为 fileprivate。但是如果用 fileprivate,属性的作用域就会更大,可能会不小心造成属性的滥用。

    struct Date {
        fileprivate let secondsSinceReferenceDate: Double
    }
    ...

    而在 Swift 4 中,private 的属性的作用域扩大到了 extension 中,并且被限定在了 struct 和 extension 内部,这样就不需要再改成 fileprivate 了。

    类型和协议的组合类型

    考虑以下如下代码:

    protocol Shakeable {
        func shake()
    }
    
    extension UIButton: Shakeable { /* ... */ }
    extension UISlider: Shakeable { /* ... */ }
    
    func shakeEm(controls: [???]) {
        for control in controls where control.state.isEnabled {
        }
        control.shake()
    }
    

    ???处怎么写呢?在Swift 3中可以这么写。

    func shakeEm(controls: [UIControl]) {
        for control in controls where control.isEnabled {
            if control is Shakeable {
                (control as! Shakeable).shake()
            }
        }
    }

    在Swift 4中,如果将类型和协议用 & 组合在一起使用,代码就可以这么写了。

    protocol Shakeable {
        func shake()
    }
    
    extension UIButton: Shakeable { /* ... */ }
    extension UISlider: Shakeable { /* ... */ }
    
    func shakeEm(controls: [UIControl & Shakeable]) {
        for control in controls where control.state.isEnabled {
            control.shake()
        }// Objective-C API
    @interface NSCandidateListTouchBarItem<CandidateType> : NSTouchBarItem
    @property (nullable, weak) NSView <NSTextInputClient> *client;
    @end
    }

    Associated Type 追加Where 约束语句

    在 Swift 4 中可以在 associated type 后面声明的类型后追加 where 语句,其语法格式如下:

    associatedtype Element where <xxx>

    下面是 Swift 4 标准库中 Sequence 中 Element 的声明:

    protocol Sequence {
        associatedtype Element where Self.Element == Self.Iterator.Element
        // ...
    }

    它限定了 Sequence 中 Element 这个类型必须和 Iterator.Element 的类型一致。通过 where 语句可以对类型添加更多的约束,使其更严谨,避免在使用这个类型时做多余的类型判断。

    Key Paths 语法

    先来看看Swift 3的Key Paths语法:

    @objcMembers class Kid: NSObject {
        dynamic var nickname: String = ""
        dynamic var age: Double = 0.0
        dynamic var friends: [Kid] = []
    }
    
    var ben = Kid(nickname: "Benji", age: 5.5)
    
    let kidsNameKeyPath = #keyPath(Kid.nickname)
    
    let name = ben.valueForKeyPath(kidsNameKeyPath)
    ben.setValue("Ben", forKeyPath: kidsNameKeyPath)
    
    

    在Swift 4中上面的代码可以这样写:

    struct Kid {
        var nickname: String = ""
        var age: Double = 0.0
        var friends: [Kid] = []
    }
    
    var ben = Kid(nickname: "Benji", age: 8, friends: [])
    
    let name = ben[keyPath: \Kid.nickname]
    ben[keyPath: \Kid.nickname] = "BigBen"
    
    

    相比 Swift 3,Swift 4 的 Key Paths 具有以下优势:

    1. 类型可以定义为 class、struct;
    2. 定义类型时无需加上 @objcMembers、dynamic 等关键字;
    3. 性能更好;
    4. 类型安全和类型推断,例如 ben.valueForKeyPath(kidsNameKeyPath) 返回的类型是
      Any,ben[keyPath: \Kid.nickname] 直接返回 String 类型;
    5. 可以在所有值类型上使用;

    下标支持泛型

    Swift 支持通过下标来读写容器中的数据,但是如果容器类中的数据类型定义为泛型,以前的下标语法就只能返回 Any,在取出值后需要用 as? 来转换类型。在Swift 4中,下标也可以使用泛型。

    struct GenericDictionary<Key: Hashable, Value> {
        private var data: [Key: Value]
    
        init(data: [Key: Value]) {
            self.data = data
        }
    
        subscript<T>(key: Key) -> T? {
            return data[key] as? T
        }
    }
    
    let dictionary = GenericDictionary(data: ["Name": "Xiaoming"])
    
    let name: String? = dictionary["Name"] // 不需要再写 as? String
    
    

    字符串

    Unicode 字符串

    在 Unicode 中,有些字符是由几个其它字符组成的,比如 é 这个字符,它可以用 \u{E9} 来表示,也可以用 e 字符和上面一撇字符组合在一起表示 \u{65}\u{301}。例如:

    这里写图片描述
    这个 family 是一个由多个字符组合成的字符,打印出来的结果为 一个家庭。上面的代码在 Swift 3 中打印的 count 数是 4,在 Swift 4 中打印出的 count 是 1。

    更快的字符处理速度

    Swift 4 的字符串优化了底层实现,对于英语、法语、德语、西班牙语的处理速度提高了 3.5 倍。对于简体中文、日语的处理速度提高了 2.5 倍。

    去掉了 characters

    Swift 3 中的 String 需要通过 characters 去调用的属性方法,在 Swift 4 中可以通过 String 对象本身直接调用,例如:

    let values = "one,two,three..."
    var i = values.characters.startIndex
    
    while let comma = values.characters[i...<values.characters.endIndex].index(of: ",") {
        if values.characters[i..<comma] == "two" {
            print("found it!")
        }
        i = values.characters.index(after: comma)
    }
    
    

    在Swift 4 可以把上面代码中的所有的 characters 都去掉:

    let values = "one,two,three..."
    var i = values.startIndex
    
    while let comma = values[i...<values.endIndex].index(of: ",") {
        if values[i..<comma] == "two" {
            print("found it!")
        }
        i = values.index(after: comma)
    }
    

    One-sided Slicing

    Swift 4 新增了一个语法糖 … 可以对字符串进行单侧边界取子串。例如:

    let values = "abcdefg"
    let startSlicingIndex = values.index(values.startIndex, offsetBy: 3)
    let subvalues = values[startSlicingIndex...] // One-sided Slicing
    // defg
    
    

    将String 当做 Collection 来用

    Swift 4 中 String 可以当做 Collection 来用,并不是因为 String 实现了 Collection 协议,而是 String 本身增加了很多 Collection 协议中的方法,使得 String 在使用时看上去就是个 Collection。例如:
    翻转字符串

    let abc: String = "abc"
    print(String(abc.reversed()))
    // cba

    遍历字符

    let abc: String = "abc"
    for c in abc {
        print(c)
    }
    /*
    a
    b
    c
    */

    Map、Filter、Reduce

    // map
    let abc: String = "abc"
    _ = abc.map {
        print($0.description)
    }
    
    // filter
    let filtered = abc.filter { $0 == "b" }
    
    // reduce
    let result = abc.reduce("1") { (result, c) -> String in
        print(result)
        print(c)
        return result + String(c)
    }
    print(result)
    
    

    Substring

    这里写图片描述

    在 Swift 中,String 的背后有个 Owner Object 来跟踪和管理这个 String,String 对象在内存中的存储由内存其实地址、字符数、指向 Owner Object 指针组成。Owner Object 指针指向 Owner Object 对象,Owner Object 对象持有 String Buffer。当对 String 做取子字符串操作时,子字符串的 Owner Object 指针会和原字符串指向同一个对象,因此子字符串的 Owner Object 会持有原 String 的 Buffer。当原字符串销毁时,由于原字符串的 Buffer 被子字符串的 Owner Object 持有了,原字符串 Buffer 并不会释放,造成极大的内存浪费。
    在 Swift 4 中,做取子串操作的结果是一个 Substring 类型,它无法直接赋值给需要 String 类型的地方。必须用 String() 包一层,系统会通过复制创建出一个新的字符串对象,这样原字符串在销毁时,原字符串的 Buffer 就可以完全释放了。例如:

    let big = downloadHugeString()
    let small = extractTinyString(from: big)
    
    mainView.titleLabel.text = small // Swift 4 编译报错
    
    mainView.titleLabel.text = String(small) // 编译通过
    
    

    多行字符串字面量

    Swift 3 中写很长的字符串只能写在一行。

    func tellJoke(name: String, character: Character) {
        let punchline = name.filter { $0 != character }
        let n = name.count - punchline.count
        let joke = "Q: Why does \(name) have \(n) \(character)'s in their name?\nA: I don't know, why does \(name) have \(n) \(character)'s in their name?\nQ: Because otherwise they'd be called \(punchline)."
        print(joke)
    }
    tellJoke(name: "Edward Woodward", character: "d")
    

    字符串中间有换行只能通过添加 \n 字符来代表换行。Swift 4 可以把字符串写在一对 “”” 中,这样字符串就可以写成多行。

    func tellJoke(name: String, character: Character) {
        let punchline = name.filter { $0 != character }
        let n = name.count - punchline.count
        let joke = """
            Q: Why does \(name) have \(n) \(character)'s in their name?
            A: I don't know, why does \(name) have \(n) \(character)'s in their name?
            Q: Because otherwise they'd be called \(punchline).
            """
        print(joke)
    }
    tellJoke(name: "Edward Woodward", character: "d")
    
    

    Swift 标准库

    Encoding and Decoding

    当需要将一个对象持久化时,需要把这个对象序列化,往常的做法是实现 NSCoding 协议,写过的人应该都知道实现 NSCoding 协议的代码写起来很痛苦,尤其是当属性非常多的时候。Swift 4 中引入了 Codable 帮我们解决了这个问题,这和Java等面向对象语言有异曲同工之妙。例如:

    struct Language: Codable {
        var name: String
        var version: Int
    }

    想让这个 Language 对象的实例持久化,只需要让 Language 符合 Codable 协议即可,Language 中不用写别的代码。符合了 Codable 协议以后,可以选择把对象 encode 成 JSON 或者 PropertyList。

    Encode操作

    let swift = Language(name: "Swift", version: 4)
    if let encoded = try? JSONEncoder().encode(swift) {
        // 把 encoded 保存起来
    }

    Decode操作

    if let decoded = try? JSONDecoder().decode(Language.self, from: encoded) {
        print(decoded.name)
    }

    Sequence

    在Swift 3中,

    protocol Sequence {
        associatedtype Iterator: IteratorProtocol
        func makeIterator() -> Iterator
    }

    由于 Swift 4 中的 associatedtype 支持追加 where 语句,所以 Sequence 做了这样的改进。

    protocol Sequence {
        associatedtype Element
        associatedtype Iterator: IteratorProtocol where Iterator.Element == Element
        func makeIterator() -> Iterator
    }
    
    

    Swift 4 中获取 Sequence 的元素类型可以不用 Iterator.Element,而是直接取 Element。例如:

    protocol Sequence {
        associatedtype SubSequence: Sequence 
            where SubSequence.SubSequence == SubSequence,
                  SubSequence.Element == Element
    }
    
    

    通过 where 语句的限定,保证了类型正确,避免在使用 Sequence 时做一些不必要的类型判断。

    Protocol-oriented integers

    整数类型的协议也做了修改,新增了 FixedWidthInteger 等协议,具体的协议继承关系如下:
    这里写图片描述

    Dictionary and Set enhancements

    这里简单的罗列了Dictionary 和 Set 增强的功能点:

    • 通过 Sequence 来初始化;
    • 可以包含重复的 Key
    • Filter 的结果的类型和原类型一致
    • Dictionary 的 mapValues 方法
    • Dictionary 的默认值
    • Dictionary 可以分组
    • Dictionary 可以翻转

    NSNumber

    在 Swift 4 中,把一个值为 999 的 NSNumber 转换为 UInt8 后,能正确的返回 nil,而在 Swift 3 中会不可预料的返回 231。

    let n = NSNumber(value: 999)
    let v = n as? UInt8 // Swift 4: nil, Swift 3: 231

    MutableCollection.swapAt(::)

    MutableCollection 现在有了一个新方法 swapAt(::) 用来交换两个位置的值,例如:

    var mutableArray = [1, 2, 3, 4]
    mutableArray.swapAt(1, 2)
    print(mutableArray)
    // 打印结果:[1, 3, 2, 4]

    Xcode改进

    New Build System

    Xcode 9 引入了 New Build System,可在 Xcode 9 的 File -> Project Settings… 中选择开启。
    这里写图片描述

    预编译 Bridging Headers 文件

    对于 Swift 和 Objective-C 混合的项目,Swift 调用 Objective-C 时,需要建立一个 Bridging Headers 文件,然后把 Swift 要调用的 Objective-C 类的头文件都写在里面,编译器会读取 Bridging Headers 中的头文件,然后生成一个庞大的 Swift 文件,文件内容是这些头文件内的 API 的 Swift 版本。然后编译器会在编译每一个 Swift 文件时,都要编译一遍这个庞大的 Swift 文件的内容。

    有了预编译 Bridging Headers 以后,编译器会在预编译阶段把 Bridging Headers 编译一次,然后插入到每个 Swift 文件中,这样就大大提高了编译速度(苹果宣称 Xcode 9 和 Swift 4 对于 Swift 和 Objective-C 混合编译的速度提高了 40%)。

    COW Existential Containers

    Swift 中有个东西叫 Existential Containers,它用来保存未知类型的值,它的内部是一个 Inline value buffer,如果 Inline value buffer 中的值占用空间很大时,这个值会被分配在堆上,然而在堆上分配内存是一个性能比较慢的操作。

    Swift 4 中为了优化性能引入了 COW Existential Containers,这里的 COW 就代表 “Copy-On-Write”,当存在多个相同的值时,他们会共用 buffer 上的空间,直到某个值被修改时,这个被修改的值才会被拷贝一份并分配内存空间。

    移除未调用的协议实现

    struct Date {
        private let secondsSinceReferenceDate: Double
    }
    
    extension Date: Equatable {
        static func ==(lhs: Date, rhs: Date) -> Bool {
            return lhs.secondsSinceReferenceDate == rhs.secondsSinceReferenceDate
        }
    }
    
    extension Date: Comparable {
        static func <(lhs: Date, rhs: Date) -> Bool {
            return lhs.secondsSinceReferenceDate < rhs.secondsSinceReferenceDate
        }
    }
    
    

    例如,上面的代码中,Date 实现了 Equatable 和 Comparable 协议。编译时如果编译器发现没有任何地方调用了对 Date 进行大小比较的方法,编译器会移除 Comparable 协议的实现,来达到减小包大小的目的。

    减少隐式 @objc 自动推断

    在项目中想把 Swift 写的 API 暴露给 Objective-C 调用,需要增加 @objc。在 Swift 3 中,编译器会在很多地方为我们隐式的加上 @objc,例如当一个类继承于 NSObject,那么这个类的所有方法都会被隐式的加上 @objc。这样很多并不需要暴露给 Objective-C 也被加上了 @objc。大量 @objc 会导致二进制文件大小的增加。

    class MyClass: NSObject {
        func print() { ... } // 包含隐式的 @objc
        func show() { ... } // 包含隐式的 @objc
    }

    在 Swift 4 中,隐式 @objc 自动推断只会发生在很少的当必须要使用 @objc 的情况,比如:

    1. 复写父类的 Objective-C 方法
    2. 符合一个 Objective-C 的协议

    其它大多数地方必须手工显示的加上 @objc。减少了隐式 @objc 自动推断后,Apple Music app 的包大小减少了 5.7%。

    兼容

    Xcode 9 中同时集成了 Swift 3.2 和 Swift 4。

    1. Swift 3.2 完全兼容 Swift 3.1,并会在过时的语法或函数上报告警告。
    2. Swift 3.2 具有 Swift 4 的一些写法,但是性能不如 Swift 4。
    3. Swift 3.2 和 Swift 4 可以混合编译,可以指定一部分模块用 Swift 3.2 编译,一部分用 Swift 4 编译。
    4. 迁移到 Swift 4 后能获得 Swift 4 所有的新特性,并且性能比 Swift 3.2 好。

    当 Xcode 正式版发布后,现有的 Swift 代码可以直接升级到 Swift 3.2 而不用做任何改动,后续可以再迁移到 Swift 4。或者直接迁移到 Swift 4 也可以,Swift 4 相比 Swift 3 的 API 变化还是不大的,很多第三方库都可以直接用 Swift 4 编译。Swift 1 到 2 和 Swift 2 到 3 的迁移的痛苦在 3 到 4 的迁移上已经大大改善了。

    参考资料:

    展开全文
  • Swift4.0】属性

    2017-12-28 15:19:36
    希望对Swift的学习者有所帮助,使用的编写工具:JQNote  InNote(iPhone) 属性是把值和某个类,结构体或者枚举联系在一起。存储型属性存储一个实例的常量和变量值部分,然而计算型属性会计算出(而不是...

    翻译能力有限,如有不对的地方,还请见谅!希望对Swift的学习者有所帮助,使用的编写工具:JQNote    InNote(iPhone)


    属性是把值和某个类,结构体或者枚举联系在一起。存储型属性存储一个实例的常量和变量值部分,然而计算型属性会计算出(而不是存储)一个值。类,结构体和枚举都支持计算型属性,而存储型属性只有类和结构体支持。这两种属性通常跟某个类型的实例关联。然而,属性也可以跟类型本身关联起来,这种属性称之为类型属性。另外,你可以定义一个属性观察者来检测该属性值的改变。


    存储属性

    一个存储属性是一个常量或者变量,被存储作为一个类或者结构体实例的一部分。你可以在定义它的时候给它一个缺省值,也可以在初始化方法中设置和修改存储属性的初始化值,即便是该存储属性是常量。如果你创建了一个常量结构体实例,那么就不能修改该实例的属性,即使属性被声明为变量。


    let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)

    // this range represents integer values 0, 1, 2, and 3

    rangeOfFourItems.firstValue = 6

    // this will report an error, even though firstValue is a variable property”


    因为结构体是值类型,当一个结构体实例被声明为常量,那么它的所有属性都不能被改变。但是对于类来说,是引用类型,如果类实例被声明为常量,你还可以改变它的变量属性的。


    懒存储属性

    这种属性直到它第一次被使用才会初始化。在声明存储属性前面加上lazy关键字就表示为懒存储属性。


    你必须总是声明懒存储属性为变量(var),因为直到实例初始化完成之后,它的初始化值可能不能被获取,而常量属性必须总是在实例初始化完成之前有一个值。


    class DataImporter {

        /*DataImporter is a class to import data from an external ”

    “file.

         The class is assumed to take a non-trivial amount of time to initialize.

         */


        var filename = "data.txt"

        // the DataImporter class would provide data importing functionality here

    }

     

    class DataManager {

        lazy var importer = DataImporter()

        var data = [String]()

        // the DataManager class would provide data management functionality here

    }

     

    let manager = DataManager()

    manager.data.append("Some data")

    manager.data.append("Some more data")”


    如上面的例子,因为importer 被声明为一个lazy 属性,DataImporter实例仅仅是当 importer属性第一次被调用获取的时候,才会创建。

    print(manager.importer.filename)

    // the DataImporter instance for the importer property has now been created

    // Prints "data.txt”


    计算型属性

    计算型属性实际上不会存储一个值,相反,它们提供了一个getter和一个可选的setter方法来直接获取或者设置其它属性的值。

    struct Point {

        var x = 0.0, y = 0.0

    }


    struct Size {

        var width = 0.0, height = 0.0

    }


    struct Rect {

        var origin = Point()

        var size = Size()

        var center: Point {

            get {

                let centerX = origin.x + (size.width / 2)

                let centerY = origin.y + (size.height / 2)

                return Point(x: centerX, y: centerY)

            }

            set(newCenter) {

                origin.x = newCenter.x - (size.width / 2)

                origin.y = newCenter.y - (size.height / 2)

            }

        }

    }


    var square = Rect(origin: Point(x: 0.0, y: 0.0),

                      size: Size(width: 10.0, height: 10.0))

    let initialSquareCenter = square.center

    square.center = Point(x: 15.0, y: 15.0)


    只读的计算型属性

    一个计算型的属性,如果只有getter方法,没有setter方法,那就被认为是一个只读的计算属性。你可以声明一个简单的只读计算属性,不需要get关键字:

    struct Cuboid {

        var width = 0.0, height = 0.0, depth = 0.0

        var volume: Double {

            return width * height * depth

        }

    }


    let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)

    print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")

    // Prints "the volume of fourByFiveByTwo is 40.0”


    属性观察者

    属性观察者观察和响应一个属性值的改变。当属性值每次被set的时候,观察者都会被调用,即使新的值和当前的值相同。除了lazy属性,你可以将属性观察者添加到任何存储属性:


    >> willSet :值被存储之前调用

    >> didSet :新值被存储之后调用


    当你实现了willSet,它会传递一个新的值作为一个常量参数。你也可以给这个参数特定一个名字。如果你没有写这个参数名,那么默认newValue可以被使用。类似,如果实现了didSet,你也可以特定一个参数名或者使用默认的oldValue。

    class StepCounter {

        var totalSteps: Int = 0 {

            willSet(newTotalSteps) {

                print("About to set totalSteps to \(newTotalSteps)")

            }

            didSet {

                if totalSteps > oldValue  {

                    print("Added \(totalSteps - oldValue) steps")

                }

            }

        }

    }


    类型属性

    实例属性属于某个类型的实例,每次在创建实例的时候,它有自己的一系列属性。与其它实例是分开的。

    你也可以定义属于类型自己的属性,而不属于每个该类型的实例。类型属性只会拷贝一次,无论该类型被创建了多少个实例。

    不像存储实例属性,存储类型属性必须赋一个缺省值,这是因为类型自己没有一个初始化器可以在初始化的时候给类型属性设置值。

    定义一个类型属性,使用staic关键字:

    struct SomeStructure {

        static var storedTypeProperty = "Some value."

        static var computedTypeProperty: Int {

            return 1

        }

    }

    enum SomeEnumeration {

        static var storedTypeProperty = "Some value."

        static var computedTypeProperty: Int {

            return 6

        }

    }

    class SomeClass {

        static var storedTypeProperty = "Some value."

        static var computedTypeProperty: Int {

            return 27

        }

        class var overrideableComputedTypeProperty: Int {

             return 107

        }

    }


    获取和设置类型属性:

    print(SomeStructure.storedTypeProperty)

    // Prints "Some value."

    SomeStructure.storedTypeProperty = "Another value."

    print(SomeStructure.storedTypeProperty)

    // Prints "Another value."

    print(SomeEnumeration.computedTypeProperty)

    // Prints "6"

    print(SomeClass.computedTypeProperty)

    // Prints "27”



    展开全文
  • 免费下载地址:https://itunes.apple.com/cn/app/id1320746678◈ 不看视频不看书,手把手带您学习Swift语言◈ 利用手指来互动式学习Swift 4.0◈ 无痛上手,比观看视频、阅读书籍更加有趣、更加有效的学习方式 ◈ 变...

    免费下载地址:https://itunes.apple.com/cn/app/id1320746678

    ◈ 不看视频不看书,手把手带您学习Swift语言
    ◈ 利用手指来互动式学习Swift 4.0
    ◈ 无痛上手,比观看视频、阅读书籍更加有趣、更加有效的学习方式 
    ◈ 变被动学习为主动学习,真正的Swift语言一点通,是您学习Swift语言的最佳方式


    【Swift4互动教程是什么】
    Swift4互动教程是一款简单、有趣、互动式的学习Swift的新工具。是第一款互动式学习Swift的工具。此应用将向您展示基于Swift 4.0的绝大部分功能点。
    就像有一名专业的教师手把手地教您最新、最实用的Swift编程技巧。您将学会怎么使用Xcode来快速、直接地表达您的想法与创意。
    另外,本应用119节课都包含互动模式,同时也支持观赏模式,当您在互动式学习中肢体疲劳时,可以切换至此模式,这样意味着您同时也拥有了119节教学影片。 

    【Swift4互动教程主要包括哪些内容】
    包含常量与变量、基本数据类型,以及Swift语言中的新数据类型—元组型和可选型的内容。同时还讲解了运算符和表达式、流程控制语句、字符和字符串、集合类型、函数和闭包。此外,Swift面向对象的枚举、结构体、类,以及内存管理、协议与抽象类型、错误处理、链式编程、iOS开发中的常见概念等内容也有所涉及。在第八章我们使用Swift语言实现了栈、队列、二叉树等数据结构,还实现了常见的8种排序算法。最后一章则包含了证书的创建、项目的架构、开发、打包、上传和发布一整套流程,供您学以致用。 部分内容如下:
    - 使用Playground学习Swift
    - Swift语言中的常量和变量
    - Swift的标识符和关键字
    - Swift的表达式Expressions
    - 给Swift代码添加注释语句
    - Swift的几个打印输出语句
    - 在控制台输出类的实例及其属性

    - Swift的(Boolean)布尔类型
    - Swift的(Int)整形类型
    - Swift的(Float)和(Double)浮点类型
    - 字符串(String)及对字符(Characters)的遍历
    - Swift字符串的使用详解
    - Swift中的元组(Tuples)
    - 基本数据类型之间的互相转换
    - 一维数组(Array)的使用详解
    - 多维数组的创建和遍历
    - 数组的几种遍历方式
    - 字典(Dictionary)的使用详解

    - Swift的一元、二元和三元运算符
    - Swift的位运算符和防溢出运算符
    - 比较运算符和区间运算符
    - 使用for-in循环遍历数组
    - 使用循环语句获得序列中的最小值
    - switch-case语句的实例解析
    - continue、break和fallthrough的区别
    - while和repeat-where循环语句
    - if和if-let判断语句的使用解析

    - 函数的参数和返回值
    - 函数的外部参数名
    - 创建拥有任意数量参数的函数
    - 函数的输入输出inout参数解析
    - 给函数的参数设置默认的取值
    - 使用函数作为另一个函数的参数
    - 函数类型的解析
    - 使用函数类型作为函数的返回类型
    - 函数可以拥有多个返回值
    - 藏在函数内部的函数
    - 递归函数的使用解析
    - Swift那些非常实用的内部函数

    - Swift的枚举(enum)类型及遍历
    - 给枚举类型添加方法
    - Swift的结构(struct)类型及其下标(subscript)
    - 类(class)的初始化方法、属性和方法
    - 类的引用(reference)特征
    - 类和结构两个类型的比较
    - 类属性的set和get方法解析
    - 类属性的willSet和didSet方法解析
    - 类析构方法(deinit)的使用
    - 给类添加下标(subscript)
    - 类的静态方法(class func)
    - 将一个类的实例作为另一个类的属性
    - 类的继承以及方法的重写(override)
    - 父类在实例类型转化时的应用
    - 使用is语句检查实例的类型
    - 使用Any表示任意值类型

    - 使用扩展(extension)扩展类型的属性
    - 使用extension对方法进行扩展
    - 使用协议(protocol)进行方法的声明
    - 问号?和感叹号!的用法解析
    - Swift中的闭包(Closure)详解
    - Swift语言中的泛型编程
    - Swift的do-try-catch错误处理模式
    - 实例的引用特征和Swift的内存管理
    - 实例的交叉引用和弱引用(weak)
    - Swift的懒加载(lazy initialization)使用解析

    - 范围Range、ClosedRange和NSRange的使用
    - 点CGPoint和变形CGAffineTransform的使用
    - 尺寸CGSize的使用详解
    - 范围CGRect的使用详解
    - 使用NSString对字符串进行各种操作
    - 日期Date和DateFormatter日期的格式化
    - 日历Calendar和日期组件DateComponents
    - 日历Calendar和时区TimeZone
    - 使用定时组件Timer执行定时任务
    - 使用UserDefaults和归档方式存取用户数据
    - 路径URL的使用详解
    - 使用DispatchGroup管理线程组
    - 使用UIScreen查询设备屏幕信息
    - 使用UIColor设置界面组件的颜色属性

    - Swift语言中的两种单例模式
    - Swift语言中的三种消息传递模式
    - 闭包在定时任务、动画和线程中的使用
    - 通过protocol在两个对象中进行消息传递
    - 通过间接代理进行对象间的消息传递
    - 通过属性进行对象间的消息传递
    - 使用通知的方法进行对象间的数据传递
    - 使用performSegue在故事板页面之间进行数据传递
    - Swift中的栈Stack和队列Queue详解
    - Swift中的链表LinkedList详解
    - 使用Swift创建一个二叉树BinaryTreeNode
    - 冒泡排序算法的Swift实现
    - 选择排序算法的Swift实现
    - 快速排序算法的Swift实现
    - 插入排序算法的Swift实现
    - 希尔排序算法的Swift实现
    - 归并排序算法的Swift实现
    - 基数排序算法的Swift实现
    - 堆排序算法的Swift实现

    - 在iTunesConnect中创建产品ACTHelper
    - 在Xcode9中创建新项目ACTHelper
    - 创建开发证书和发布证书及其它文件
    - 在ACTHelper项目中使用CocoaPod管理插件
    - 创建BaseViewController作为控制器的基类
    - 创建App的欢迎页面
    - 登陆页面:创建自定义视图及相关组件
    - 登陆页面:创建自定义表单Row以及基控制器
    - 创建用户登陆页面
    - 用户注册账号信息的输入和短信验证码
    - 用户注册头像和科目信息输入页面
    - 用户注册考试成绩输入页面及相关自定义组件
    - 试题解析页面及相关自定义组件
    - 试题科目列表及答案列表等自定义组件
    - 创建试题解析列表页面和试卷选择页面
    - 创建试题详情页面和浮动菜单组件
    - 试题原文显示页面和数学公式的渲染
    - 账号设置列表页面和分享、反馈、评分功能
    - 会员个人信息设置页面和登出功能
    - App发布前的设置以及打包、上传和提交审核
    - 更多内容等待您的探索!!!










    【相关互动教程】
    Xcode9.0互动教程
    https://itunes.apple.com/cn/app/id1063100471

    iOS开发中的神兵利器
    https://itunes.apple.com/cn/app/id1209739676

    Excel2016互动教程
    https://itunes.apple.com/cn/app/id1090726089

    Photoshop CC互动教程精装版
    https://itunes.apple.com/cn/app/id822431555

    Illustrator CC互动教程
    https://itunes.apple.com/cn/app/id1005557436

    Photoshop CS5互动教程完全版:
    https://itunes.apple.com/cn/app/id976566883

    Photoshop脚本互动教程
    https://itunes.apple.com/cn/app/id926846601
    展开全文
  • #swift - 类与结构体 **阅读此文章前,您已经有一定的Object-C语法基础了!** 在Swift中,类和结构体都是对数据和方法进行封装的常用做法!首先我们来看看他们的共同之处: 1. 都可以有属性和方法; 2. 都有构造...

    Swift - 站在OC的基础上快速的学习Swift的类与结构体

    阅读此文章前,您已经有一定的Object-C语法基础了!


    2014年,Apple推出了Swift,最近开始应用到实际的项目中。
    首先我发现在编写Swift代码的时候,经常会遇到XCode不能提示,卡顿,直接闪退等问题,尤其是在Swift和OC混编时。(不知道其他开发者是否也有这样的经历,但是我相信这样的问题,很快会得到解决)
    然后感觉Swift并不像网上很多朋友说的那样简单。有很多细节问题是值得注意的,甚至有很多思路是颠覆了传统的开发语言的!又有很多特性是结合了其他编程语言的优点!Swift,我个人觉得是趋势,是目前最前卫的开发语言,结合了众多开发语言的优点!
    网上已经有很多Swift相关的论文和博客了,这里我不做推荐和转载了!我归纳一下类和结构体,以及相关的知识吧!


    Swift中,类和结构体都是对数据和方法进行封装的常用做法!首先我们来看看他们的共同之处:

    1. 都可以有属性和方法;
    2. 都有构造器;
    3. 都支持附属脚本;
    4. 都支持扩展;
    5. 都支持协议。

    然后我们来看看他们的不同之处:

    1. 类有继承;
    2. 结构体有一个自动生成的逐一初始化构造器;
    3. 在做赋值操作时,结构体总是被拷贝(Array有特殊处理);
    4. 结构体可以声明静态的属性和方法;
    5. 从设计模式的角度来分析,类的设计更侧重于对功能的封装,而结构体的设计更侧重于对数据的封装。(汽车就是一个复杂的类,内部各部件之间有着复杂的联系,一个部件出了问题可能会影响到其他部件甚至整个汽车,而书架就像一个简单的结构体,他存储着各种图书,各图书之间又是相对独立的)

    一、构造过程

    1. 默认值

    在OC 类和结构的成员属性会隐式的给出默认值,对象的默认值是nil,基本数据类型的默认值是0。但是在 Swift 中属性必须显示的设置默认值,Swift会在调用构造器之前调用默认值构造器对所有在设置了默认值的属性进行初始化。

    当一个构造过程完成的时候,被构造的类或者结构体的实例的存储属性都会是有值的,否则编译错误!

        class A : SuperClass {
            var _a = 1      // 默认值 = Int(1)
            var _b: Int?    // 默认值 = nil
            var _c: Int     // 无默认值,必须在构造器中赋值
            var _d: Int!    // 默认值 = nil
    
            init() {
                _c = 1      // 在调用父类的构造器之前,必须给_c赋值,否则编译错误
                super.init()
            }
            ...
        }
    

    2. 构造器

    类似与OC的 -(instance)init 方法。和OC最大的区别是 OC 初始化完成后返回的是这个对象的指针,而Swift初始化完成后返回的是这个对象的引用。

    根据构造器的实际构造过程可将构造器分为 **便利构造器** 和 **指定构造器**,但只有指定构造器才是真实的构造器,便利构造器只是为指定构造器添加一个便利的参数传入,或者增加一些附加操作。

    以下几点在开发的时候需要注意:

    1. 类和结构体都需要在构造器完成对所有存储属性的初始化;
    2. 子类在调用父类的构造器之前必须确保本类声明的所有的存储属性都已经有值了;
    3. 便利构造器必须直接或者间接的调用本类的指定构造器。

       class A : SomeClass {
           var _a: Int
           var _b = 1_000
      
           // 指定构造器
           init() {
               self._a = 5     // 如果是这样声明的 'var _a: Int = 5' or 'var _a = 5',那么init()构造器可以不写而直接调用
               super.init()
           }
      
           // 指定构造器
           init(a: Int) {      
               self._a = a     // 因为 _a 属性没有默认值,所以在调用 super.init() 前必须给 _a 赋值,否则编译错误!
               super.init() 
           }
      
           // 便利构造器
           convince init(a: Int, b: Int) {
               self.init(a: a + b)         // 直接调用指定构造器
           }
      
           // 便利构造器
           convince init(a: Int, b: Int, c: Int) {
               self.init(a: a, b: b + c)   // 间接调用指定构造器
           }   
           ...
       }
      

    3. 析构器

    和OC的 dealloc 很像,这里不多做解释了。

    class A {
        ...
        deinit {    
            //...  析构器内部处理
        }
        ...
    }
    

    二、属性

    OC中的类有属性,也有实例变量。但Swift中将类的实例变量和属性统一用属性来实现。

    1. 存储属性

    简单来说就是一个成员变量/常量。Swift可以为存储属性增加属性监视器来响应属性值被设置时的变化。

    class SomeClass {
        let _a = 100        // 常量
        var _b: Int         // 没有默认值的变量
        var _c = 200        // 默认值=200的Int变量
        var _d: Int = 200 { // 默认值=200的Int变量,如果增加了属性监视器,必须显示的声明变量类型
            didSet {
                println("A 的 _c 属性 didSet = old:\(oldValue) -> \(self._c)")   // oldValue 表示曾经的值
            }
            willSet {
                println("A 的 _c 属性 willSet = \(self._c) -> new:\(newValue)")  // newValue 表示将会被设置的值
            }
        }
    }
    

    2. 计算属性

    计算属性并不存储任何数据,他只是提供 set/get 的便利接口

    class A {
        class var a: Int {  // 这是类的计算属性 (区别于下面类的实例的计算属性)
            return 1001
        }
    
        private(set) var _b = 100   // 外部可以访问,但不能修改
        private var _a = 100        // 私有变量,外部不能访问
        var a: Int {                // 只读计算属性
            return _a
        }
        var b: Int {                // 可读可写的计算属性
            get {
                retrun _a
            }
            set {
                _a = newValue       // newValue 表示的是输入的值
            }
        }
    }
    

    3. 延迟存储属性

    相信大家都听说过延迟加载(懒加载),就是为了避免一些无谓的性能开销,在真正需要该数据的时候,才真正执行数据加载操作。 Swift可以使用关键字 lazy 来声明延迟存储属性,延迟存储属性在默认值构造器中不会被初始化,而是在第一次使用前进行初始化! 虽然没被初始化,但是编译器会认为他是有值的。

    全局的常量或者变量都是延迟加载的, 包括结构体的静态属性也是延迟加载的。

    let some = A()
    
    class A {
        lazy var view = UIView(frame: CGRectZero) // 定义了一个延迟存储属性      ...
    }
    

    4. 静态属性

    结构体可以使用关键字 static 来声明静态存储属性。(枚举也可以有) Swift的类不支持静态属性,也不支持静态临时变量。
    这可以作为Swift中声明单例的一种实现方法

    class Tools {
        class func sharedInstance() -> Tools {
            struct Static {
                static let sharedInstance = QNTools()
            }
            return Static.sharedInstance
        }
    }   
    

    三、方法

    Swift的类和结构体都可以定义自己的方法!(OC的结构体是没有方法的)

    1. 参数

    一个方法的参数有局部参数名称和外部参数名称,一样时写一个即可! Swift的方法的参数非常灵活,可以是值,可以是引用,可以是闭包,可以是元组... Swift的方法的返回值跟参数一样灵活

    这里给出一个简单的加法方法来展示方法的参数

    class A {
        // eg. 一个简单的相加方法
        // 完整版
        class func sum1(let a/*外部参数名称*/ aValue/*内部参数名称*/: Int, let b/*外部参数名称*/ bValue/*内部参数名称*/: Int) -> Int {
            return aValue + bValue
        }
    
        // 当函数参数的外部和内部参数相同的时候,可以只写一个,  此时第一个参数的名称在调用时是隐藏的
        class func sum2(a: Int, b: Int) -> Int {
            return a + b
        }
    
        // 使用 _ 符号,可以在调用的时候隐藏函数参数名称,第一个参数默认就是隐藏的
        class func sum3(a: Int, _ b: Int) -> Int {
            // 内嵌函数的参数名称,都是可以隐藏的。而不用使用 _ 符号声明
            func sum4(a: Int, b: Int) -> Int {
                return a + b
            }
            return sum4(a, b)
        }
    
        // 可使用 let/var 关键字来声明参数是作为常量还是变量被传入,(如果是常量,可以不用显示的写 let)
        class func sum4(let a: Int, _ b: Int) -> Int {
            // 内嵌函数的参数名称,都是可以隐藏的。而不用使用 _ 符号声明
            func sum4(a: Int, b: Int) -> Int {
                return a + b
            }
            return sum4(a, b)
        }
    
        // 可使用 let/var 关键字来声明参数是作为常量还是变量被传入,(如果是常量,可以不用显示的写 let)
        class func sum5(let a: Int, let _ b: Int) -> Int {
            // 内嵌函数的参数名称,都是可以隐藏的。而不用使用 _ 符号声明
            return a + b
        }
    
        class func sum6(var a: Int, var _ b: Int) -> Int {
            // 内嵌函数的参数名称,都是可以隐藏的。而不用使用 _ 符号声明
            a++
            b++
            return a + b
        }
    
        // 可使用 inout 关键字,传引用
        class func add(inout value: Int) {
            value++
        }
    }
    
    A.sum1(a: 1, b: 2)          // result: 3
    A.sum2(1, b: 2)             // result: 3
    A.sum3(1, 2)                // result: 3
    var aTemp: Int = 1001       // aTemp = 1001
    A.add(&aTemp)
    aTemp                       // aTemp = 1002
    A.sum5(1, 2)               // result: 3
    A.sum6(1, 2)               // result: 5
    

    2. 实例方法

    类或者结构体的实例所拥有的方法!

    class A {
        private(set) var a: Int = 100
        func reset() -> Void {
            self.a = 100
        }
    }
    
    struct S {
        var a: Int = 100
        mutating func reset() -> Void { // 注意: 在结构体和枚举的实例方法中如果需要修改属性,则需要增加 mutating 字段
            self.a = 100
        }
    }
    

    3. 类方法

    Swift 中类的本身也是一个实例。他没有存储属性、但拥有计算属性和方法!

    参考 “1.参数” 中的示例
    

    4. 静态方法

    结构体可以使用关键字 static 来声明静态方法。

    struct S {
        static func name() -> String {
            return "Liuyu"
        }
    }
    

    四、附属脚本

    Swift 提供了附属脚本的语法来简化类似查询的行为。如访问一个数组的第n个元素,array[n], 访问一个字典的值 dictionary[“key”],这些都可以通过附属脚本来实现。
    这里给出一个通过字符串类型的索引来查询数组中的元素的例子。

    // 扩展一个通过字符串类型的位置来访问数据的附属脚本
    extension Array {
        subscript(index: String) -> T? {
            if let iIndex = index.toInt() {
                return self[iIndex]
            }
            return nil
        }
    }
    let array = ["Liu0", "Liu1", "Liu2"]
    array[1]    // result : Liu1
    array["1"]! // result : Liu1
    

    五、继承

    和OC一样,Swift类可以通过继承来获取父类的属性和方法(有限制)。
    Swift的类的在继承上增加了很多安全措施!

    class SomeSuperClass {
        func someFunc1() {
            ...
        }
        // 定义不能被子类重写的方法,需要加上 final 关键字
        final func someFunc2() {
            ...
        } 
    }
    
    class SomeClass : SomeSuperClass {
        // 重载父类的方法,需要加上 override 关键字
        override func someFunc1() {
            ...
            super.someFunc1()
        }
    
        // 不能被子类重写的方法
        override func someFunc2() {     // Error
            ...
            super.someFunc2()
        }
    }
    

    六、扩展

    扩展就是向一个已有的类、结构体或枚举类型添加新功能。 这包括在没有权限获取原始源代码的情况下扩展类型的能力(即逆向建模)。 扩展和 OC 中的类别(categories)类似,但又有很多细微的区别

    1. 扩展没有名字,一旦扩展就会应用到整个工程(模块)
    2. 在扩展中如果要重载现有的方法,需加上override关键字 (不建议修改现有的方法)
    3. 可定义新的嵌套类型

    这里给出一个数学项目中计算距离时的一个扩展。

    typealias Distance = Double
    extension Distance {
        var km: Double { return self/1_000.0 }
        var m : Double { return self }
        var cm: Double { return self*100.0 }
        var mm: Double { return self*1_000.0 }
    }
    
    let distance = Distance(1000)   // 1000m的距离
    distance.km     // result : 1.0     (km)
    distance.m      // result : 1000.0  (m)
    distance.cm     // result : 100.0   (cm) 


    题外话:
    很少写博客,也许会一些纰漏或者错误的地方,如果你发现了请指出来 !!谢谢!!  

    展开全文
  • Swift4.0复习结构体

    2019-07-30 23:39:04
    /** 定义了一个结构体 */ struct Structure { /// 一个常量存储式实例属性, /// 并直接为它初始化 let constProperty = 10 /// 一个变量存储式实例属性 var property: Int /// 初始化器 i....
  • Swift4.0 study1 语法

    2018-01-19 10:29:45
    swift学习第一天 :语法 1.常量和变量 var 修饰变量 (可以修改) let 修饰常量(不可变) print代理oc中的NSLog输出 2.数据类型转换:Swift是强语言(OC是弱语言)故进行转换时必须指明数据类型,即...
  • 希望对Swift的学习者有所帮助,使用的编写工具:JQNote InNote(iPhone) 存储属性 一个存储属性是一个常量或者变量,被存储作为一个类或者结构体实例的一部分。你可以在定义它的时候给它一个缺省值,也...
  • swift4.0-11 类和结构体

    2019-04-28 00:40:49
    代码学习swift4.0, 类和结构体 // // main.swift // SwiftLearn11-类和结构体 // // Created by iOS on 2018/5/7. // Copyright © 2018年 weiman. All rights reserved. // impor...
  • //// ViewController.swift// 011-数组//// Created by 庄壮勇 on 2018/1/3.// Copyright © 2018年 Personal. All rights reserved.//import UIKitclass ViewController: UIViewController { override func ...
  • &lt;一&gt;字符串OC的字符串是一个对象: 0.NSString(不可变的),NSSMutableString(可变的) 1.获取字符串长度:str.lengthSwift的字符串是一个结构体:... 1.swift的字符串支持遍历 2.获取字符串长...
  • Swift4.0源代码最新20180210.函数和闭包.playground 11.初始化和释放.playground 12.协议protocol.playground 13.类和结构体的区别.playground 14.枚举.playground 15.扩展.playground 16.下标.playground 17.泛型....
  • 苹果官方的文档一般都很少去看,笔者参考官方文档和各路大神的经验,写下了一份基于Swift 4.0 的编码规范,并会持续更新,欢迎大家补充指正。 编码格式 命名规范 语法规范 1. 编码格式 1.1 使用二元...
  • 所以慢慢多了很多OC混编Swift的项目,但是其实swift调用OC还是挺简单的,把OC项目慢慢转成swift问题不大。swift可以算是OC更上层的语言,我这里说的坑都是关于Swift转OC的,很奇葩吧,还有把Swift项目转成OC的,一句...
  • swift4.0 新特性

    2017-08-21 11:09:18
    #1.添加Codable协议,方便自定义数据类型序列化 #2.添加定义多行字符串语法 #3.... #4....#5....在Objective-C中值类型的相互影响是十分糟糕的。比如NSCoding协议,类继承它之后,我们需要在类中重写自定义的 e
  • 解决方法有很多种,但是要想全局处理防止按钮重复点击,最优雅的方法就是利用Runtime在运行时进行方法交换来处理。 实现思路 ... 使用Runtime关联属性;...Swift 4.0中initialize()已经被废弃 所以需要自定义一...
  • swift结构体和类有着更多的相同之处,在一般的使用中能够做到互相替换。我们可以先看看官方文档的描述: Unlike other programming languages, Swift doesn’t require you to create separate interface and ...
  • OC中的字符串是一个对象,继承于NSObject,但是Swift中的字符串是一个结构体,因此Swift中的字符串性能比OC中要高,实际应用举例如下: var str1 = "zyt" var str2 = "ssg" //单纯拼接两个...
  • Swift、Xcode和Cocoa入门指南(iOS9 Programming Fundamentals With swift)  第二章 函数  Swift语法中最具特色也最重要的就是声明和调用函数的方式;  所有代码都位于函数中,而动作则是由函数触发的;  ...
  • 素材:Language Guide初次接触 Swift,建议先看下 A Swift Tour ,否则思维转换会很费力,容易卡死或钻牛角尖。同样是每一章只总结3个自己认为最重要的点。这样挺好!强迫你去思考去取舍。以后再看,也方便快速重建...
1 2 3 4 5 ... 20
收藏数 692
精华内容 276
热门标签