总结一下多年来所学习到的 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 复制代码