總結一下多年來所學習到的 Swift 編碼技巧express
///OutStream 中有一個
open func write(_ buffer: UnsafePointer<UInt8>, maxLength len: Int) -> Int 方法
複製代碼
如何將數據以流的形式存儲呢json
let data = Data ///事實上 data.bytes 其實就是 unsigned char *的數組 在 Swift 中能夠用[UInt8]數組來表示 ///或者使用(data as NSData).bytes 並不優雅 畢竟要儘可能脫離OC的框架 ///data是結構體 使用[UInt8]構造方法獲得data的byte數組 let bytes = [UInt8](data) ///使用UnsafePointer<UInt8>構造方法生成指針 outputStream?.write(UnsafePointer<UInt8>(bytes), maxLength: bytes.count) 複製代碼
按道理元組是不必遍歷的,可是在 swift 中仍是有一些應用場景的,好比獲取設備型號swift
///在結構體utsname中 設備型號machine的定義以下(在OC中是一個char *指針) public var machine: (Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8) /* [XSI] Hardware type */ 複製代碼
256個元素的元組 用 0,1,2,3 這樣取要到何時,最然可能10位之前就能碰到\0
提早退出了 能夠使用反射來獲得一個元素的數組數組
var systemInfo = utsname() uname(&systemInfo) let mirror = Mirror(reflecting: systemInfo.machine) let type = mirror.children.map {String(UnicodeScalar(UInt8( $0.value as! Int8)))}.joined() print(type)/// iPhone8,1 複製代碼
let view = UIView() var observation = view.observe(\UIView.frame, options: [.new]) { (_, change) in ///frame的類型時CGRect 不像原來從字典取值還須要轉換 let frame = change.newValue } ///invalidate() will be called automatically when an NSKeyValueObservation is deinited /// 監聽對象會在銷燬的時候自動調用invalidate()方法的 因此要提早強引用監聽對象 而後跟隨引用者一塊兒銷燬就行了 observation.invalidate() 複製代碼
self
事實上這是一個 bug,可是開發者很喜歡 不須要再定義 strongSelf 這樣的起個新名字的變量了 固然 這樣閉包中也不會在拿到真正的 self
了bash
var enclosure = {[weak self] in guard let `self` = self else {return} self.xxx } 複製代碼
func ASLog(_ value: Any... , fileName : String = #file,function : String = #function, line : Int32 = #line ){ #if DEBUG print("文件名稱:\((fileName as NSString).lastPathComponent) Function: \(function) Line:\(line)") print("調試信息:\(value)") print("============================================") #endif } ASLog("哈哈") 文件名稱:coding.playground Function: __lldb_expr_1 Line:31 調試信息:["哈哈"] ============================================ 複製代碼
有返回值得方法 暫時可能不會寫邏輯 提早 return 一個值就行了 也能夠直接 fatalError() 這樣你要是忘寫代碼了 還能直接給你崩潰markdown
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { fatalError() ///fatalError("implement later") } 複製代碼
泛型的好處很少說了閉包
方法中標記了某個類型,返回值也是跟這個類型相關框架
這個泛型的類型在合適的時候肯定便可ide
下面的例子則是由等號左邊的值得類型肯定的
方法舉例:
定義一個解析工具類,傳入一個 json 返回一個模型的數組 (HandyJSON 自己就能夠用[T].self.self.deserialize(from: json)解析)
protocol HandyJSON {} struct Book: HandyJSON { var id = 0 var name = "" } struct Student: HandyJSON { var id = 0 var name = "" } class Parse { class func returnModels<T: HandyJSON>(_ json: String) -> [T] { return [] } } var res1: [Book] = Parse.returnModels("") var res2: [Student] = Parse.returnModels("") var res3: [Book] res3 = Parse.returnModels("") 複製代碼
像 Array 的 map 方法也是一個帶泛型函數
@inlinable public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]
複製代碼
泛型的類型能夠經過結果值來肯定,也能夠在閉包中返回值肯定
var names1: [String] = res1.map { $0.name } var names2 = res2.map { (s) -> String in return s.name } 複製代碼
一句話:只須要在 T 出現的地方肯定類型就能夠了
有的語言是用if NOT condition : expression
來作非的判斷
固然我會以爲!更簡單一些
那麼如何在 Swift 中實現這種非的判斷呢,請看下面的代碼,騷操做,無卵用
let NOT = (!) let condition = true if NOT(condition) { expression } 複製代碼
Swift3.0之後 sizeof()函數就已經不能使用了,不過能夠使用MemoryLayout < T > 來獲取數據佔據內存空間
public enum MemoryLayout<T> { public static var size: Int { get } //連續的內存佔用量,以字節爲單位 public static var stride: Int { get }//存儲在連續存儲器或存儲器中的一個實例的開始到下一個實例的開始的字節數 public static var alignment: Int { get }//默認對齊方式,以字節位單位 public static func size(ofValue value: T) -> Int public static func stride(ofValue value: T) -> Int public static func alignment(ofValue value: T) -> Int public static func offset(of key: PartialKeyPath<T>) -> Int? } struct Point { let x: Double let y: Double let isFilled: Bool } // MemoryLayout<Point>.size == 17 // MemoryLayout<Point>.stride == 24 // MemoryLayout<Point>.alignment == 8 複製代碼
在 Swift 中
UnsafePointer 對應 C 中的const Type * UnsafeMutablePointer 對應Type * 經過 Unsafe 也能夠看出來指針操做是不安全的 Swift 中不能直接經過 & 直接獲得一個指針變量,可是依然能夠用&獲取變量地址
func incrementor(_ ptr: UnsafeMutablePointer<Int>) {
ptr.pointee += 1
}
var a = 10
incrementor(&a)
a // 11
var arr = [11,22]
incrementor(&arr)
arr// [12,22]
複製代碼
能夠經過+ - 操做來實現指針的位移,以下:
func incrementor(_ ptr: UnsafeMutablePointer<Int>) {
(ptr+1).pointee += 1
// ptr.pointee += 1
}
var a = 10
var b = 11
incrementor(&a)
a // 10
b // 12
var arr = [11,22]
incrementor(&arr)
arr // [11,23]
複製代碼
原理同 OC 中的 @autoreleasepool
public func autoreleasepool<Result>(invoking body: () throws -> Result) rethrows -> Result func test() { for _ in 0..<999 { autoreleasepool { let a = loadBigData() } } } 複製代碼
OC中 NSObject對象有 description 屬性 能夠在 NSLog 時自定義輸出 在 swift 中須要遵照CustomStringConvertible這個協議
struct Person: CustomStringConvertible{ var age: Int var name: String var description: String { "姓名: \(name) 年齡:\(age)" } } let p = Person(age: 18, name: "小明") print(p) ///姓名: 小明 年齡:18 print("\(p)")///姓名: 小明 年齡:18 複製代碼