[Swift Tips 讀書筆記]從 Objective-C 到 Swift(五)

  1. 輸出格式化
  1. Options
  2. 數(shù)組 enumerate
  3. 類型編碼 @encode
  4. C 代碼調(diào)?和 @asmname

--

輸出格式化

OC中使用%@、%g、%d等進行輸出格式化。

Swift支持的輸出方法print支持字符串插值。字符串插值時直接使用類型的StreamablePrintable、DebugPrintable協(xié)議(按先后順序,前面的沒有實現(xiàn)的話就用后面的)中的方法返回的字符串并進行打印。

打印Double 保留兩位小數(shù)如下

extension Double {
    func formatPrint(_ f: String) -> String {
          return String(format:"%\(f)f",self)
    }
}

let b = 2.345
 _ = String(format:"%.2f",b)  // 2.35
print("b is \(b)")  //2.345
let pr = b.formatPrint(".2")
print("pr is \(pr)")  //2.35

--

Options

OC中的Options

typedef NS_OPTIONS(NSUInteger, UIRectCorner) {
    UIRectCornerTopLeft     = 1 << 0,
    UIRectCornerTopRight    = 1 << 1,
    UIRectCornerBottomLeft  = 1 << 2,
    UIRectCornerBottomRight = 1 << 3,
    UIRectCornerAllCorners  = ~0UL
};

// 可以使用 `|` `&` 這樣的按位邏輯符對這些選項操作,因為Options的定義都是這么按位錯開的。
[UIBezierPath bezierPathWithRoundedRect:self.view.bounds byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight) cornerRadii:CGSizeMake(5, 5)];

Swift中的Options是一個滿足OptionSet協(xié)議的struct,以及一組靜態(tài)的get屬性

public struct UIRectCorner : OptionSet {

    public init(rawValue: UInt)
    public static var topLeft: UIRectCorner { get }
    public static var topRight: UIRectCorner { get }
    public static var bottomLeft: UIRectCorner { get }
    public static var bottomRight: UIRectCorner { get }
    public static var allCorners: UIRectCorner { get }
}

 UIBezierPath.init(roundedRect: self.view.frame, byRoundingCorners: [.topLeft,.topRight], cornerRadii: CGSize.init(width: 5, height: 5))

--

數(shù)組 enumerate

快速枚舉數(shù)組的EnumerateGenerator,元素是一個元組

    let arr = [2,3,4,56,7,8,9]
    var result = 0
    for (index, num) in arr.enumerated() {
        result +=  num
        if index == 4 {
            break
        }
    }
    print("result is \(result)")

--

類型編碼 @encode

類型編碼是編譯器對每種類型都給定了一個字符串作為該類型唯一的編碼

OC中獲取某種類型編碼使用@encode()

char *stringEncode = @encode(NSString);//NSString=#
char *intEncode = @encode(int);//i

Swift使用自己的Metatype處理類型,并且在運行時保留這些類型的信息,所以swift沒有保留這個關鍵字。swift中就不能獲取任何類型的類型編碼了,但是可以通過NSValueobjcType屬性獲取對應值的類型指針。

class NSValue {
    var objCType: [UnsafePointer]<[Int8] { get }
}

let range = NSRange.init()
let rValue = NSValue.init(range: range).objCType  //{_NSRange=QQ}
print(String(validatingUTF8: rValue) ?? "")

let pi: Double = 3.14159
let dValue = NSNumber.init(value: pi).objCType  // d
print(String(validatingUTF8: dValue) ?? "")

--

C 代碼調(diào)?和 @asmname

  • Darwin涵蓋了絕大數(shù)C標準庫中的內(nèi)容。導入使用import Darwin。實際編碼中,UIKit包含了Foundation, Foundation又包含了Darwin,不用我們手動再導入了。

Darwin中包含了C標準庫中大多數(shù)內(nèi)容

swift做好了Darwin中的類型的自動轉(zhuǎn)換對應,可以直接使用Swift的類型。
做好了`Darwin`中的類型的自動轉(zhuǎn)換對應

  • 對于自己創(chuàng)建的C文件,導入的時候同swift調(diào)用OC代碼一樣。建立一個bridge文件,在橋文件中導入頭文件

      // test.h
      void doSomething();        
      // test.m
      void doSomething() {
          // do something    
      }
    
      //Module-Bridging-Header.h
      #import "test.h"
      
      // a.swift
      doSomething()
    
  • 可以使用@asmname符號,通過方法名字,將C函數(shù)直接映射為swift中的函數(shù)。這時候就不用橋文件了。

    //將 C 的 test ?法映射為 Swift 的 c_test ?法
    @asmname("doSomething") func c_test() -> Void
    

除了上面一個作用外,@asmname還承擔著和@objc的‘重命名swift類中類和方法名’類似的任務,可以將C語言中不認的swift元素字符轉(zhuǎn)為ASCII碼,以便使用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容