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

总结一下多年来所学习到的 Swift 编码技巧

1.从 Data 中获取 bytes

///OutStream 中有一个 
open func write(_ buffer: UnsafePointer<UInt8>, maxLength len: Int) -> Int 方法
复制代码

如何将数据以流的形式存储呢

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 中还是有一些应用场景的,比如获取设备型号

///在结构体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 这样的起个新名字的变量了 当然 这样闭包中也不会在拿到真正的 self

 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.方法中泛型的使用

泛型的好处不多说了

方法中标记了某个类型,返回值也是跟这个类型相关

这个泛型的类型在合适的时候确定即可

下面的例子则是由等号左边的值得类型确定的

方法举例:

定义一个解析工具类,传入一个 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
}
复制代码

转载于:https://juejin.im/post/5cf8942af265da1b695d4e5d

猜你喜欢

转载自blog.csdn.net/weixin_34365417/article/details/91414409