[Swift]coding的一些技巧(瞎編中...)

總結一下多年來所學習到的 Swift 編碼技巧express

1.從 Data 中獲取 bytes

///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)
複製代碼

2.遍歷元組

按道理元組是不必遍歷的,可是在 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
複製代碼

3.Swift 中 KVO 的使用

SwiftKVO 簡單介紹安全

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()
複製代碼

4.閉包中使用不會引發循環引用的 self

事實上這是一個 bug,可是開發者很喜歡 不須要再定義 strongSelf 這樣的起個新名字的變量了 固然 這樣閉包中也不會在拿到真正的 selfbash

var enclosure = {[weak self] in
    guard let `self` = self else {return}
    self.xxx 
}
複製代碼

5.Swift 自定義 log

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
調試信息:["哈哈"]
============================================

複製代碼

6. 拋異常,消 error (眼不見心不煩)

有返回值得方法 暫時可能不會寫邏輯 提早 return 一個值就行了 也能夠直接 fatalError() 這樣你要是忘寫代碼了 還能直接給你崩潰閉包

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        fatalError()
        ///fatalError("implement later")
}
複製代碼

7.方法中泛型的使用

泛型的好處很少說了框架

方法中標記了某個類型,返回值也是跟這個類型相關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 出現的地方肯定類型就能夠了

8.使用 NOT 代替 ! 作非的判斷(然並卵)

有的語言是用if NOT condition : expression來作非的判斷

固然我會以爲!更簡單一些

那麼如何在 Swift 中實現這種非的判斷呢,請看下面的代碼,騷操做,無卵用

let NOT = (!)

let condition = true

if NOT(condition) {
    expression
}
複製代碼

9.Swift 中的 sizeof()

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

複製代碼

10.指針操做

在 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]
複製代碼
相關文章
相關標籤/搜索