[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]
复制代码
相关文章
相关标签/搜索