2017-10-18 18:23:24 bddzzw 阅读数 10274
/*
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)
        })
        
    }
}
*/


良言一句三冬暖,恶语伤人六月寒。无论工作还是生活,都不要拿脾气当做与他人博弈的武器。即使侥幸一时赢了,最终也只是两败俱伤。一言一语间,完成的是沟通,体现的是修养。或许我们不能成为优秀的别人,却完全可以做更好的自己。
2016-06-29 21:14:05 wj610671226 阅读数 9449

如何快速将Swift2.0的项目过渡到Swift3.0

      今年WWDC之后,相信大家都已经更新到iOS10和Xcode8.0beta版本尝鲜了,其中包括SiriKit、新的语音识别框架SFSpeechRecognizer、通知框架(UserNotifications.framework、UserNotificationsUI.framework)等等都等待着我们去探索和发现呢!大笑

        我个人认为最先接触的必然是Swift3.0语法的变化了,想当初我们手把手用Swift2.0撸出的项目,后续必然会过渡到Swift3.0中,难道我们又要一行一行的去修改代码吗?想想就不开心大哭,下面介绍较快的方法吧项目过渡到Swift3.0中。

准备好Xcode8.0Beta,将我们之前的项目用Xcode8.0打开。打开之后Xcode会有一个提示下面我们跟着截图一起走吧。

1、这个提示是说:你的项目包含早期版本的Swift代码,询问你是否更新到Swift3


2、点击next

3、选择Swift3


4、这里选择我们需要更新代码的Targets


5、耐心等待


6、点击Save保存


在上面这张图中我们便可以清楚的看到Swift语法的变化,左边是最新的语法,右边是之前的语法版本

当然通过上面的操作只能把绝大部分的语法修改过来,但是有一些部分的代码需要我们根据自己的实际情况去修改它才能完全过渡到Swift3中。

比如:1、类似i++这样的代码需要手动修改为i += 1

   2、第三方的OC库,调用也可能发生一点点的改变,手动修改(高德地图)

   3、使用了C语言风格的for循环也需要自己修改

   ......自己去探索吧小伙伴大笑

总结Swift3中语法详细的变化参考文章:https://gold.xitu.io/entry/576bd4595bbb500059463426

一篇讲解Swift3.0变化的英文网站(个人感觉很不错):https://www.raywenderlich.com/135655/whats-new-swift-3

补:总结Swift语法变化的好文章 http://tech.glowing.com/cn/swift3/

适配 Swift 3 的一点小经验和坑:https://imtx.me/archives/2064.html




2017-08-15 11:23:18 xiangzhihong8 阅读数 2622

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 阅读数 1811

创建完了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>

2018-06-20 14:49:13 qq_37269542 阅读数 669

最近因为项目需求需要对项目代码进行升级,从之前的swift2.0版本升级到swift4.1版本。现将升级过程中遇到的一些语法变化与大家分享一下,希望会对大家有所帮助,

Swift 2.0 --> Swift 4.0

1.self.edgesForExtendedLayout = UIRectEdge.None  -->  self.edgesForExtendedLayout = UIRectEdge.init(rawValue: 0)

2.UINavigationBar.appearance().titleTextAttributes=NSDictionary(object:UIColor.whiteColor(), forKey:NSForegroundColorAttributeName) as? [String : AnyObject]  -->  UINavigationBar.appearance().titleTextAttributes = [NSAttributedStringKey.foregroundColor : UIColor.white]
[NSForegroundColorAttributeName: UIColor.white]  -->  [NSAttributedStringKey.foregroundColor : UIColor.white]

3.使用Alamofire获取statusCode: res.result.error?.code  -->  res.response?.statusCode

4.CGRectZero  -->  CGRect.zero

5.从其他线程回到主线程的方法:
   dispatch_async(dispatch_get_main_queue(), { () -> Void in 

   })		--> 

   DispatchQueue.main.async {

   }

 6.	UILabel获取字体大小的属性boundingRectWithSize的改变:
 	let size = body.boundingRectWithSize(CGSizeMake(CGFloat(w-20), CGFloat(10000.0)),options:NSStringDrawingOptions.UsesLineFragmentOrigin,  attributes: [NSFontAttributeName:UIFont.systemFontOfSize(12)],context:nil)     -->
 	let size = body.boundingRect(with: CGSize.init(width: CGFloat(Constants.SCREEN_W - 20), height: CGFloat(10000.0)),options:NSStringDrawingOptions.usesLineFragmentOrigin,  attributes:[NSAttributedStringKey.font : UIFont.systemFont(ofSize: 12)],context:nil)

 7.let myMutableString = NSMutableAttributedString(string: (!body.isEmpty ? body : "") , attributes: [NSFontAttributeName:UIFont(name: "HelveticaNeue", size: 12.0)!])	 -->  
   let myMutableString = NSMutableAttributedString.init(string: (!body.isEmpty ? body : ""), attributes: [NSAttributedStringKey.font : UIFont(name: "HelveticaNeue", size: 12.0)!])
 
 8.let paragraphStyle = NSMutableParagraphStyle()
 	myMutableString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle,range: NSRange(location:0,length:myMutableString.length))   -->
 	myMutableString.addAttribute(NSAttributedStringKey.paragraphStyle, value: paragraphStyle, range: NSRange.init(location: 0, length: myMutableString.length))

 9.SDWebImage的用法改变:
   headImg.sd_setImageWithURL(NSURL(string: self.images[indexPath.row] as! String), placeholderImage: UIImage(named: "default_logo"))     -->   
   headImg.sd_setImage(with: NSURL.init(string: self.images[indexPath.row] as! String)! as URL, placeholderImage: UIImage(named: "default_logo"), options: .retryFailed, completed: nil)

10. UIApplication.sharedApplication().keyWindow?.windowLevel = UIWindowLevelStatusBar    -->   UIApplication.shared.keyWindow?.windowLevel = UIWindowLevelStatusBar

11. NSCalendarUnit.Day  -->   NSCalendar.Unit.day

12. var components = cal.components([NSCalendar.Unit.day, NSCalendar.Unit.month, NSCalendar.Unit.year, NSCalendar.Unit.weekOfYear, NSCalendar.Unit.hour, NSCalendar.Unit.minute, NSCalendar.Unit.second, NSCalendar.Unit.nanosecond], from: NSDate() as Date)
	components.setValue(components.month-3, forComponent: NSCalendar.Unit.month)  -->  components.setValue(components.month! - 3, for: .month)

13. formatter.stringFromDate(cal.dateFromComponents(components)!)  -->  formatter.string(from: cal.date(from: components)!)

14. string.characters.count  -->  string.count

15. string.stringByReplacingOccurrencesOfString(" ", withString: "")	-->	   string.replacingOccurrences(of: " ", with: "")

16. for i in str.characters {
	
	}         -->     
	for i in str {

	}

17. str.removeRange(index!)  -->   str.removeSubrange(index!)

18. let alertInputTelController = UIAlertController(title: title, message: "", preferredStyle: UIAlertControllerStyle.alert)
	alertInputTelController.addTextFieldWithConfigurationHandler {

	}	  -->   
	alertInputTelController.addTextField {

	}

19. addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: NSRange.init(location: startIndex!, length: 1))   -->  
	attrString.addAttribute(.foregroundColor, value: UIColor.red, range: NSRange.init(location: startIndex!, length: 1))

20. tf.text?.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) != ""   --> 
	tf.text?.trimmingCharacters(in: NSCharacterSet.whitespaces) != ""     //检测textField中输入的字符去掉空格后是否为空的方法

21. kNewStoreInfo.setObject(tf.text!, forKey: key)   --> 
	kNewStoreInfo.setObject(tf.text!, forKey: key as NSCopying)

22. textView.text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())    -->   
	textView.text.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines)

23. //将内容同步写到文件中去(Caches文件夹下)
        let cachePath = NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: .UserDomainMask)[0]
        let path = cachePath.URLByAppendingPathComponent("log.txt")
        appendText(path, string: "\(datestr) \(consoleStr)")     

        --> 

        let cachePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        let path = cachePath.appendingPathComponent("log.txt")
        appendText(fileURL: path as NSURL, string: "\(datestr) \(consoleStr)")

24. FileManager.defaultManager().createFileAtPath(fileURL.path!, contents: nil, attributes: nil)  -->  
	FileManager.default.createFile(atPath: fileURL.path!, contents: nil, attributes: nil)

25. NSFileHandle.init(forWritingAtPath: fileURL.path!)   -->
	FileHandle.init(forWritingAtPath: fileURL.path!)

26. //找到末尾位置并添加
    fileHandle!.seekToEndOfFile()        
    fileHandle?.writeData(stringToWrite.dataUsingEncoding(NSUTF8StringEncoding)!)  -->
    fileHandle?.write(stringToWrite.data(using: String.Encoding.utf8)!)

27. string.componentsSeparatedByString(",")  -->   string.components(separatedBy: ",")

28. NSIndexPath(forRow: i, inSection: 0)  -->   NSIndexPath(row: i, section: 0)

29. NSComparisonResult.OrderedAscending  -->  ComparisonResult.orderedAscending

30. NSNotificationCenter.defaultCenter().postNotificationName("Notification_UploadImage", object: j)  -->
	NotificationCenter.default.post(name: NSNotification.Name(rawValue: "Notification_UploadImage"), object: j)

31. NSNotificationCenter.defaultCenter().postNotificationName("Notification_UploadImage", object: "error", userInfo: nil)  -->
	NotificationCenter.default.post(name: NSNotification.Name(rawValue: "Notification_UploadImage"), object: "error", userInfo: nil)

32. let startIndex =  Int("\(range.startIndex)") -->
	let startIndex =  Int("\(range.upperBound.encodedOffset)") - 1

33. // 单例模式
    class var sharedInstance: TreeNodeHelper {
        struct Static {
            static var instance: TreeNodeHelper?
            static var token: dispatch_once_t = 0
        }
        dispatch_once(&Static.token) { // 该函数意味着代码仅会被运行一次,而且此运行是线程同步
            Static.instance = TreeNodeHelper()
        }
        return Static.instance!
    }
    -->  

    //由于dispatch_once在Swift4.0也已经被废弃   通过给DispatchQueue添加扩展实现
    extension DispatchQueue { 
    private static var _onceTracker = [String]()
    public class func once(token: String, block: () -> ()) {
        objc_sync_enter(self)
        defer {
            objc_sync_exit(self)
        }
        if _onceTracker.contains(token) {
            return
        }
        _onceTracker.append(token)
        block()
    }
    
    func async(block: @escaping ()->()) {
        self.async(execute: block)
    }
    
    func after(time: DispatchTime, block: @escaping ()->()) {
        self.asyncAfter(deadline: time, execute: block)
    }
}
// 单例模式
    class var sharedInstance: TreeNodeHelper {
        
        struct Static {
            static var instance: TreeNodeHelper?
            static let _onceToken = NSUUID().uuidString
        }
        //由于dispatch_once在Swift4.0也已经被废弃  此处通过给DispatchQueue添加扩展实现
        DispatchQueue.once(token: Static._onceToken) { // 该函数意味着代码仅会被运行一次,而且此运行是线程同步
           Static.instance = TreeNodeHelper()
        }
        return Static.instance!
    }

34. let url = NSURL(string:urlString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)  -->
	let url = NSURL(string: urlString.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!)

35. dispatch_async(DispatchQueue.global(0, 0), {
                    
    })    -->   
    DispatchQueue.global().async {

    }
 
36. 在Google Maps SDK中有三个常量来表示每种类型,此属性必须设置成其中一个. 这些常量是:
	kGMSTypeNormal
	kGMSTypeTerrain
	kGMSTypeHybrid
	在使用时候的变化:
 	kGMSTypeNormal  -->  GMSMapViewType.normal

 	kGMSMarkerAnimationPop --> GMSMarkerAnimation.pop

37. let directionsData = NSData(contentsOfURL: directionsURL! as URL)  -->
	let directionsData = NSData(contentsOf: directionsURL as URL)

38. 使用Alamofire解析获取返回的error code值方法:
	res.result.error?.code   -->   res.result.error?._code


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