2017-08-15 11:23:18 xiangzhihong8 阅读数 2685
  • Swift5语言入门实例教程

    【课程概括】 包含常量与变量、基本数据类型,以及Swift语言中的新数据类型—元组型和可选型的内容。同时还讲解了运算符和表达式、流程控制语句、字符和字符串、集合类型、函数和闭包。此外,Swift面向对象的枚举、结构体、类,以及内存管理、协议与抽象类型、错误处理、链式编程、iOS开发中的常见概念等内容也有所涉及。在第八章我们使用Swift语言实现了栈、队列、二叉树等数据结构,还实现了常见的8种排序算法。第九章则包含了证书的创建、项目的架构、开发、打包、上传和发布一整套流程,供您学以致用。 【课程特点】 1、119节大容量课程:包含了Swift 5.0语言大部分知识点; 2、创新的教学模式:手把手教您iOS开发技术,一看就懂,一学就会; 3、贴心的操作提示:让您的眼睛始终处于操作的焦点位置,不用再满屏找光标; 4、语言简洁精练:瞄准问题的核心所在,减少对思维的干扰,并节省您宝贵的时间; 5、视频短小精悍:即方便于您的学习和记忆,也方便日后对功能的检索; 【移动端客户评价】 『五个星不够,想给十个。本来我是学通信的学生,发现h5可以打包成iOS app,但是继续学下去发现很多iOS资源用不了,于是就来学iOS开发,老师的课很好,我把他的iOS开发三件套课程全部买了,老师梳理的脉络很清晰,绝对可以节省你很多学习的时间成本,不用你一知半解的胡乱Google,三套课程150,绝对的良心价。远比培训班便宜,也比书便宜。还要说一句,老师的课绝对脉络清晰,不懂的概念去Google,Google完还是不懂也没关系,后续的课程慢慢就会让你理解,所以前期不懂不要急,不要急于问为什么,慢慢你就会理解为什么。好了,送给准备入坑iOS开发的大家一句话:编程不要眼高手低。』  评论人: 180470185 – Sep 3, 2018

    854 人正在学习 去看看 李发展

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 的迁移上已经大大改善了。

参考资料:

2018-01-19 14:17:50 si1279571489 阅读数 1833
  • Swift5语言入门实例教程

    【课程概括】 包含常量与变量、基本数据类型,以及Swift语言中的新数据类型—元组型和可选型的内容。同时还讲解了运算符和表达式、流程控制语句、字符和字符串、集合类型、函数和闭包。此外,Swift面向对象的枚举、结构体、类,以及内存管理、协议与抽象类型、错误处理、链式编程、iOS开发中的常见概念等内容也有所涉及。在第八章我们使用Swift语言实现了栈、队列、二叉树等数据结构,还实现了常见的8种排序算法。第九章则包含了证书的创建、项目的架构、开发、打包、上传和发布一整套流程,供您学以致用。 【课程特点】 1、119节大容量课程:包含了Swift 5.0语言大部分知识点; 2、创新的教学模式:手把手教您iOS开发技术,一看就懂,一学就会; 3、贴心的操作提示:让您的眼睛始终处于操作的焦点位置,不用再满屏找光标; 4、语言简洁精练:瞄准问题的核心所在,减少对思维的干扰,并节省您宝贵的时间; 5、视频短小精悍:即方便于您的学习和记忆,也方便日后对功能的检索; 【移动端客户评价】 『五个星不够,想给十个。本来我是学通信的学生,发现h5可以打包成iOS app,但是继续学下去发现很多iOS资源用不了,于是就来学iOS开发,老师的课很好,我把他的iOS开发三件套课程全部买了,老师梳理的脉络很清晰,绝对可以节省你很多学习的时间成本,不用你一知半解的胡乱Google,三套课程150,绝对的良心价。远比培训班便宜,也比书便宜。还要说一句,老师的课绝对脉络清晰,不懂的概念去Google,Google完还是不懂也没关系,后续的课程慢慢就会让你理解,所以前期不懂不要急,不要急于问为什么,慢慢你就会理解为什么。好了,送给准备入坑iOS开发的大家一句话:编程不要眼高手低。』  评论人: 180470185 – Sep 3, 2018

    854 人正在学习 去看看 李发展

创建完了tableView,接下来要加载一些真实的数据,用到网络请求工具,我们封装网络请求工具必然用到单例模式及闭包,一步一步进行,现在就封装网络请求类为单例模式。
在swift3.0 已经废弃dispatch_once_t 方法,故不能再用oc的方法写单例,但是Swift给出的单例模式也是极其容易的。
继承自NSObject的SCHHttpManager为网络请求类,创建这个类为单例模式

1.设置静态变量 并保证线程安全
2.获取单例类的对象的类方法

//let 是线程安全的
static let _shareManager = SCHHttpManager()
class func shareManager()->SCHHttpManager{
    return _shareManager
}



调用

print(SCHHttpManager.shareManager())
print(SCHHttpManager.shareManager())
输出:两者地址相同,故单例完成
<SCHBurro.SCHHttpManager: 0x60000000db50>
<SCHBurro.SCHHttpManager: 0x60000000db50>

2017-10-18 18:23:24 bddzzw 阅读数 10342
  • Swift5语言入门实例教程

    【课程概括】 包含常量与变量、基本数据类型,以及Swift语言中的新数据类型—元组型和可选型的内容。同时还讲解了运算符和表达式、流程控制语句、字符和字符串、集合类型、函数和闭包。此外,Swift面向对象的枚举、结构体、类,以及内存管理、协议与抽象类型、错误处理、链式编程、iOS开发中的常见概念等内容也有所涉及。在第八章我们使用Swift语言实现了栈、队列、二叉树等数据结构,还实现了常见的8种排序算法。第九章则包含了证书的创建、项目的架构、开发、打包、上传和发布一整套流程,供您学以致用。 【课程特点】 1、119节大容量课程:包含了Swift 5.0语言大部分知识点; 2、创新的教学模式:手把手教您iOS开发技术,一看就懂,一学就会; 3、贴心的操作提示:让您的眼睛始终处于操作的焦点位置,不用再满屏找光标; 4、语言简洁精练:瞄准问题的核心所在,减少对思维的干扰,并节省您宝贵的时间; 5、视频短小精悍:即方便于您的学习和记忆,也方便日后对功能的检索; 【移动端客户评价】 『五个星不够,想给十个。本来我是学通信的学生,发现h5可以打包成iOS app,但是继续学下去发现很多iOS资源用不了,于是就来学iOS开发,老师的课很好,我把他的iOS开发三件套课程全部买了,老师梳理的脉络很清晰,绝对可以节省你很多学习的时间成本,不用你一知半解的胡乱Google,三套课程150,绝对的良心价。远比培训班便宜,也比书便宜。还要说一句,老师的课绝对脉络清晰,不懂的概念去Google,Google完还是不懂也没关系,后续的课程慢慢就会让你理解,所以前期不懂不要急,不要急于问为什么,慢慢你就会理解为什么。好了,送给准备入坑iOS开发的大家一句话:编程不要眼高手低。』  评论人: 180470185 – Sep 3, 2018

    854 人正在学习 去看看 李发展
/*
Swift 中的闭包有很多优化的地方
1 根据上下文推断参数和返回值的类型
2 从单行表达式闭包中隐式返回 可以省略return
3 可以使用简化的参数如 $0 $1 意为从0或者1开始
4 提供了尾随闭包的语法
*/
//语法   parameters参数 return 隐藏了
//{(parameters) -> return type in
//    parameters
//}
//最简单的闭包//省略in的
let b = {
    print("这也是闭包")
}

//用变量记录函数 (带参数的闭包)
//带有参数的闭包
//参数返回值 实现代码  {形参->返回值 in 代码}
//带参数待返回值的闭包
let countNum = {(num1:Int,num2:Int)->Int in
    return num1+num2;
}
let count1 = countNum(2,3)


//闭包的应用场景

/*异步执行完成回调  控制器之间的回调  自定义视图的回调*/

/*  以下代码需要在项目中的.Swift文件中完成
override func viewDidLoad() {
super.viewDidLoad()
loadData { (result) in
print("获取json信息\(result)")
}
// Do any additional setup after loading the view, typically from a nib.
}
func loadData(completion: @escaping (_ result: [String])->()) -> () {
DispatchQueue.global().async {
print("耗时操作\(Thread.current)")
Thread.sleep(forTimeInterval: 1.0);
let json=["12","23","34"]
DispatchQueue.main.async(execute: {
print("主线程\(Thread.current)")
completion(json)
})
}
}
结果为:耗时操作<NSThread: 0x600000277000>{number = 3, name = (null)}
主线程<NSThread: 0x604000075a80>{number = 1, name = main}
获取json信息["12", "23", "34"]
*/

//闭包表达式
let names = ["s","b","e","h","f"]

func backwards(a1:String,a2:String)->Bool{
    return a1<a2;
}
// public func sorted(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> [Element]
var result = names.sorted(by:backwards)
print(result)

//参数名缩写
///以上代码还可以  Swift自动内联函数提供了参数名称缩写功能,您可以直接通过$0,$1,$2来顺序调用闭包的参数。
var result1 = names.sorted(by:{$0<$1})
print(result1)

//作为一个函数接受两个String类型的参数并返回Bool类型的值Swift可以自动推断出您想使用大于号的字符串函数实现:
//运算符函数
var result2 = names.sorted(by:<)
print(result2)

//尾随闭包
//例子1  尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。

var result3 = names.sorted(){$0<$1}
print(result3)



//例子2
//此时点回车函数会变成中括号的形式 也就是说如果函数的最后一个参数是闭包,函数的参数可以提前结束
//        最后一个参数直接使用{}来包装闭包的代码
//        loadData1(completion: <#T##([String]) -> ()#>)
//以下两段代码相同只不过一个是使用尾随闭包的写法
/*func loadData(completion:@escaping (_ result:([String])->())->()){
    DispatchQueue.global().async {
        print("耗时操作\(Thread.current)")
        Thread.sleep(forTimeInterval: 1.0);
        let json=["12","23","34"]
        //以下两段代码相同只不过一个是使用尾随闭包的写法
        DispatchQueue.main.async{
            print("主线程\(Thread.current)")
            completion(json)
        }
        DispatchQueue.main.async(execute: {
            print("主线程\(Thread.current)")
            completion(json)
        })
        
    }
}
*/


良言一句三冬暖,恶语伤人六月寒。无论工作还是生活,都不要拿脾气当做与他人博弈的武器。即使侥幸一时赢了,最终也只是两败俱伤。一言一语间,完成的是沟通,体现的是修养。或许我们不能成为优秀的别人,却完全可以做更好的自己。
2018-04-11 23:00:19 weixin_40840896 阅读数 417
  • Swift5语言入门实例教程

    【课程概括】 包含常量与变量、基本数据类型,以及Swift语言中的新数据类型—元组型和可选型的内容。同时还讲解了运算符和表达式、流程控制语句、字符和字符串、集合类型、函数和闭包。此外,Swift面向对象的枚举、结构体、类,以及内存管理、协议与抽象类型、错误处理、链式编程、iOS开发中的常见概念等内容也有所涉及。在第八章我们使用Swift语言实现了栈、队列、二叉树等数据结构,还实现了常见的8种排序算法。第九章则包含了证书的创建、项目的架构、开发、打包、上传和发布一整套流程,供您学以致用。 【课程特点】 1、119节大容量课程:包含了Swift 5.0语言大部分知识点; 2、创新的教学模式:手把手教您iOS开发技术,一看就懂,一学就会; 3、贴心的操作提示:让您的眼睛始终处于操作的焦点位置,不用再满屏找光标; 4、语言简洁精练:瞄准问题的核心所在,减少对思维的干扰,并节省您宝贵的时间; 5、视频短小精悍:即方便于您的学习和记忆,也方便日后对功能的检索; 【移动端客户评价】 『五个星不够,想给十个。本来我是学通信的学生,发现h5可以打包成iOS app,但是继续学下去发现很多iOS资源用不了,于是就来学iOS开发,老师的课很好,我把他的iOS开发三件套课程全部买了,老师梳理的脉络很清晰,绝对可以节省你很多学习的时间成本,不用你一知半解的胡乱Google,三套课程150,绝对的良心价。远比培训班便宜,也比书便宜。还要说一句,老师的课绝对脉络清晰,不懂的概念去Google,Google完还是不懂也没关系,后续的课程慢慢就会让你理解,所以前期不懂不要急,不要急于问为什么,慢慢你就会理解为什么。好了,送给准备入坑iOS开发的大家一句话:编程不要眼高手低。』  评论人: 180470185 – Sep 3, 2018

    854 人正在学习 去看看 李发展

该文章翻译自apple官方文档:The Swift Programming Language(Swift 4.1)

Swift 4.0 版本相对于前面几个版本来说,已经比较稳定,也终于可以利用下班时间关注和学习它了,鉴于官方文档是英文的,自己翻译过后也需要记录下来,那就一起分享吧,一定有理解不充分和不足的部分,请斧正!

既然不知从哪里开始合适,那就一页页来吧~

About Swift

Swift is a fantastic way to write software, whether it’s for phones, desktops, servers, or anything else that runs code. It’s a safe, fast, and interactive programming language that combines the best in modern language thinking with wisdom from the wider Apple engineering culture and the diverse contributions from its open-source community. The compiler is optimized for performance and the language is optimized for development, without compromising on either.

Swift is friendly to new programmers. It’s an industrial-quality programming language that’s as expressive and enjoyable as a scripting language. Writing Swift code in a playground lets you experiment with code and see the results immediately, without the overhead of building and running an app.

Swift defines away large classes of common programming errors by adopting modern programming patterns:

  • Variables are always initialized before use.

  • Array indices are checked for out-of-bounds errors.

  • Integers are checked for overflow.

  • Optionals ensure that nil values are handled explicitly.

  • Memory is managed automatically.

  • Error handling allows controlled recovery from unexpected failures.

Swift code is compiled and optimized to get the most out of modern hardware. The syntax and standard library have been designed based on the guiding principle that the obvious way to write your code should also perform the best. Its combination of safety and speed make Swift an excellent choice for everything from “Hello, world!” to an entire operating system.

Swift combines powerful type inference and pattern matching with a modern, lightweight syntax, allowing complex ideas to be expressed in a clear and concise manner. As a result, code is not just easier to write, but easier to read and maintain as well.

Swift has been years in the making, and it continues to evolve with new features and capabilities. Our goals for Swift are ambitious. We can’t wait to see what you create with it.


Swift 是一门写软件很好用的语言,不管是对于手机端,前端,后台还是任何一个可以运行代码的平台,它都是一门安全,快速,能相互影响的编程语言,它结合了最好的现代化语言思维和来自更广的苹果工程文化的智慧以及来自开源社区的多种多样的贡献。这编译器在性能方面做了优化,并且这语言在开发上做了优化,不妥协。

Swift 对于初学者是很友好的,是一门既满足工业标准又脚本语言一样充满表现力趣味编程语言

Swift通过接受现代化编程模式定义了大量的常用的编程错误的类

         变量在用之前要被初始化

         检查数组时候越界

         检查整数是否溢出

         确保nil 明确地被处理过

         自动管理内存

         错误处理允许从异常失败中控制恢复。

Swift 代码充分利用现代硬件编译和优化。它的语法和标准库是基于‘写代码很显然的方式也应该运行的最好’的指导原则设计的。

安全和快速的结合使得Swift 无论从最简单的‘hello world’还是对于开发整个操作系统,都成为一个杰出的选择

Swift 结合了强大的类型推断和模式匹配与现代的,轻量级的语法,使复杂的想法,以明确和简明的方式表达。因此,代码不仅容易编写,而且更易于阅读和维护。

Swift 已经发展多年,并且在继续发展新的特点和功能。我们的目标远大,我们已经迫不及待地想看看你能用它创造出什么了。




2018-01-21 17:18:47 liushuo19920327 阅读数 3006
  • Swift5语言入门实例教程

    【课程概括】 包含常量与变量、基本数据类型,以及Swift语言中的新数据类型—元组型和可选型的内容。同时还讲解了运算符和表达式、流程控制语句、字符和字符串、集合类型、函数和闭包。此外,Swift面向对象的枚举、结构体、类,以及内存管理、协议与抽象类型、错误处理、链式编程、iOS开发中的常见概念等内容也有所涉及。在第八章我们使用Swift语言实现了栈、队列、二叉树等数据结构,还实现了常见的8种排序算法。第九章则包含了证书的创建、项目的架构、开发、打包、上传和发布一整套流程,供您学以致用。 【课程特点】 1、119节大容量课程:包含了Swift 5.0语言大部分知识点; 2、创新的教学模式:手把手教您iOS开发技术,一看就懂,一学就会; 3、贴心的操作提示:让您的眼睛始终处于操作的焦点位置,不用再满屏找光标; 4、语言简洁精练:瞄准问题的核心所在,减少对思维的干扰,并节省您宝贵的时间; 5、视频短小精悍:即方便于您的学习和记忆,也方便日后对功能的检索; 【移动端客户评价】 『五个星不够,想给十个。本来我是学通信的学生,发现h5可以打包成iOS app,但是继续学下去发现很多iOS资源用不了,于是就来学iOS开发,老师的课很好,我把他的iOS开发三件套课程全部买了,老师梳理的脉络很清晰,绝对可以节省你很多学习的时间成本,不用你一知半解的胡乱Google,三套课程150,绝对的良心价。远比培训班便宜,也比书便宜。还要说一句,老师的课绝对脉络清晰,不懂的概念去Google,Google完还是不懂也没关系,后续的课程慢慢就会让你理解,所以前期不懂不要急,不要急于问为什么,慢慢你就会理解为什么。好了,送给准备入坑iOS开发的大家一句话:编程不要眼高手低。』  评论人: 180470185 – Sep 3, 2018

    854 人正在学习 去看看 李发展

自Swift 3.0 以来,语言已经比较成熟,用Swift语言来开发iOS App 的开发者越来越多,那么一份权威而全面的规范就很有必要了。苹果官方的文档有时间大家还是多看看,笔者参考官方文档和各路大神的经验,写下了一份基于Swift 4.0 的编码规范,并会持续更新,欢迎大家补充指正。

1. 编码格式

1.1 使用二元运算符(+, -,==, 或->)的前后都需要添加空格

let value = 1 + 2

1.2 在逗号后面加一个空格

let titleArray = [1, 2, 3, 4, 5]

1.3 方法的左大括号不要另起,并和方法名之间留有空格,注释空格

// function Define
func myFunction {
    // 处理
}

1.4 判断语句不用加括号

if typeValue == 1 {
    // 处理
}

1.5 尽量不使用self. 除非方法参数与属性同名

func setPerson(name: String, pAge: Int) {
    self.name = name
    age = pAge
}

1.6 在访问枚举类型时,使用更简洁的点语法

enum Direction {
    case north
    case south
    case east
    case west
}
let currentDirection = .west

1.7 添加有必要的注释,尽可能使用Xcode注释快捷键(⌘⌥/)

/// <#Description#>
///
/// - Parameters:
///   - tableView: <#tableView description#>
///   - section: <#section description#>
/// - Returns: <#return value description#>
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return dataList.count
}

1.8 使用 // MARK: -,按功能、协议、代理等分组

// MARK: - UITableViewDelegate

// MARK: - Action

// MARK: - Request

1.9 协议一致性:当对象要实现协议一致性时,推荐使用 extension 隔离协议中的方法集,这样让相关方法和协议集中在一起,方便归类和查找

// MARK: - UICollectionViewDelegate, UICollectionViewDataSource
extension XMHomeViewController: UICollectionViewDelegate, UICollectionViewDataSource {
	// 代理方法
}

// MARK: - HttpsRequest
extension XMHomeViewController {
	// 网络请求方法
}

1.10 当对外接口不兼容时,使用@available(iOS x.0, *) 标明接口适配的起始系统版本号

@available(iOS 8.0, *)
func myFunction() {
    //
}

2. 命名规范

2.1 常量,变量,函数,方法的命名规则使用小驼峰规则,首字母小写,类型名使用大驼峰规则,首字母大写。

class MyClass: class {
    let myImageView: UIImageView
    let myName: String
}

2.2 当命名里出现缩写词时,缩写词要么全部大写,要么全部小写,以首字母大小写为准

let htmlString = "https://www.baidu.com"
let urlString:  URLString
let userID:  UserID

class HTMLModel {
    //
}

2.3 bool类型命名时,使用is作为前缀

var isMine: Bool = false

2.4 Swift中类别(类,结构体)在编译时会把模块设置为默认的命名空间,所以不用为了区分类别而添加前缀,比如XYHomeViewController,但是为了和引用的第三方库作区分,建议可以继续使用前缀,以作为规范化处理,结构更清晰。

2.5 懒加载用来细致地控制对象的生命周期,这对于想实现延迟加载视图的UIViewController特别有用

// MARK: - 懒加载
private lazy var tableView: UITableView = {
    let tableView = UITableView.init(frame: CGRect.zero, style: .plain)
    tableView.separatorStyle = .none
    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 200
    tableView.dataSource = self
    tableView.delegate = self
    tableView.register(UINib(nibName: homeListCell, bundle: nil), forCellReuseIdentifier: homeListCell)
    return tableView
}()

2.6 当函数的第一个参数构成整个语句的介词时(如,at, by, for, in, to, with 等),为第一个参数添加介词参数标签

func login(with username: String?, password: String?) {
	//
}

3. 语法规范

3.1 可选类型拆包取值时,使用if let 判断

if let data = result.data {
    //
}

3.2 多个可选类型拆包取值时,将多个if let 判断合并

if let name = person.name, let age = person.age {
    //
}

3.3 尽量不要使用 as! 或 try!,对于可选类型Optional多使用as?,?? 可以给变量设置默认值

// 使用if let as?判断
if let name = person.name as? String {
    //
}
// 给name变量设置默认值
var name = person.name ?? ""

3.4 数组和字典变量定义时需要标明泛型类型,并使用更简洁清晰的语法

var names: [String] = []
var values: [String: Int] = [:]
var person: [String: Any] = [:]

3.5 常量定义,建议尽可能定义在类型里面,避免污染全局命名空间,如果是其他地方有可能复用的cell可以定义在类型外面

static let homeListCell = "HomeListCell"

class HomeListCell: UITableViewCell {
    static let kHomeCellHeight = 80.0
    //
}

3.6 当方法最后一个参数是Closure类型,调用时建议使用尾随闭包语法

UIView.animateWithDuration(1.0) {
     self.myView.alpha=0
}

3.8 最短路径规则:当编码遇到条件判断时,左边的距离是黄金路径或幸福路径,因为路径越短,速度越快。guard 就为此而生的。

func login(with username: String?, password: String?) throws -> LoginError {
  guard let username = username else { 
    throw .noUsername 
  }
  guard let password = password else { 
    throw .noPassword
  }
  // 处理登录
}

3.9 循环遍历使用for-in表达式

// 循环
for _ in 0..<list.count {
  print("items")
}
// 遍历
for(index, person) in personList.enumerate() {
    print("\(person)is at position #\(index)")
}
// 间隔2位循环
for index in 0.stride(from: 0, to: items.count, by: 2) {
  print(index)
}
// 翻转
for index in (0...3).reverse() {
    print(index)
}

4. Swift 4.2 新特性

4.1 CaseIterable协议:定义的枚举遵循CaseIterable协议后,编译时Swift 会自动合成一个allCases属性,是包含枚举的所有case项的数组

enum NetState: CaseIterable {
    case wifi
    case hotWifi
    case mobile
    case none
}
for item in NetState.allCases {
    print(item)
}

4.2 #warning 主要用于标记一些工作还没有完成或者需要完善,Xcode 会发出一个警告;#error 标记错误,Xcode 会发出一个编译错误这样你的代码就完全不能编译

#warning("列表刷新需要优化")

#if os(macOS)
#error("MyLibrary is not supported on macOS.")
#endif

4.3 新增 allSatisfy():一种检查序列中的所有元素是否满足条件的新方法

// 判断数组的所有元素是否全部大于80
let scores = [86, 88, 95, 92]
// 返回一个BOOL
let passed = scores.allSatisfy({ $0 > 80 })
print(passed)
// 输出:true

4.4 新增 last(where:) 和 lastIndex(where:) 方法来获取数组中满足条件的最后的元素和索引值

let a = [10, 20, 30, 40, 50, 30, 20]
// 获取满足条件的元素
print(a.last(where: { $0 > 30 }))   //50
// 获取满足条件的元素的索引
print(a.lastIndex(where: { $0 > 25 }))   //4

4.5 新增 random() 随机数方法来生成一个随机数, 只需提供一个随机数范围即可

// 随机数
let ranInt = Int.random(in: 0..<10)
let ranFloat = Float.random(in: 0..<10)

let a = [10, 20, 30, 40, 50, 30, 20]
// 对数组重新洗牌, 重新随机排序返回一个数组
let shuffled = a.shuffled()
// 获取数组中的一个随机元素,空数组返回nil
let random = a.randomElement() 

4.6 新增 removeAll(where:) 方法,高效地执行根据条件删除操作

var names = ["John", "Michael", "Graham", "Andy", "Eric", "Andy"]
names.removeAll { $0.hasPrefix("Andy") }
print(names)
// 输出:["John", "Michael", "Graham", "Eric"]

5. Swift 5.0 新特性

5.1 ABI(Application Binary Interface)稳定:ABI定义了函数如何调用,数据如何在内存中呈现,元数据在哪里,以及如何访问等底层交互。之前的Swift版本中ABI还没稳定,所以每一个APP,都自己包含它Swift版本所对应的Swift Dynamic Library。ABI稳定之后,Swift动态库将包含在iOS操作系统里,它将兼容每一个Swift版本。

5.2 新增 @dynamicCallable 为Swift添加了一个新属性,允许使用一个简单的语法糖像调用函数一样调用命名类型,需要实现下面两个方法中的一个:

func dynamicallyCall(withArguments args: [Int]) -> Double
func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> Double
// 定义方式
@dynamicCallable
struct RandomNumberGenerator {
    func dynamicallyCall(withArguments args: [Int]) -> Double {
        let numberOfZeroes = Double(args.first ?? 0)
        let maximum = pow(10, numberOfZeroes)
        return Double.random(in: 0...maximum)
    }
}
// 调用方式
let random = RandomNumberGenerator()
let num = random(2)
// random(2)等同于random.dynamicallyCall(withArguments: [2])

5.3 修改:定义一个带有(可变参数 => 数组参数)的枚举

enum X {
    case foo(bar: [Int]) 
} 
func baz() -> X {
    return .foo(bar: [0, 1, 2, 3]) 
} 

5.4 新增创建原始字符串的功能,以及创建多行字符串

let quote = "Alice: \"How long is forever?\" White Rabbit: \"Sometimes, just one second.\""
let rain = #"The "rain" in "Spain" falls mainly on the Spaniards."#
let multiline = #"""
    The answer to life,
    and everything is \#(answer).
    """#

5.5 Swift 5中无论有多少个嵌套的可选,最后返回值永远只是一个可选值,使用try?

// 类型: let messages: String?
let messages = try? user?.getMessages()
print(messages ?? "")

5.6 新增了一个函数 count(where:),可以获取数组中符合条件的元素的个数

let arr = [1, 28, 3, 40, 5, 6]
let count = arr.count(where: { $0 > 10 })
print(count)  // 2

5.7 在 Swift4.x 的版本中有两个函数 compactMap 和 mapValues
compactMap: 返回一个操作后得到的新的数组, 类似flatMap
mapValues: 对字典的value值执行操作, 返回改变value后的新的字典
Swift5.0 新增了一个函数 compactMapValues 返回一个对value操作后的新字典, 并且自动过滤不符合条件的键值对

let guys = [
    "Hudson": "30",
    "Clarke": "40",
    "Robinson": "50",
    "Hartis": "DNF"
]
let comMap = guys.compactMapValues({ Int($0) + 3 })
print(comMap)
// ["Clarke": 43, "Robinson": 53, "Hudson": 33]

Swift3.3 -> Swift 4.0

阅读数 42

没有更多推荐了,返回首页