我用Xcode +python寫的第一個(gè)OS X app

前兩天剛訂閱了bestswifter大大的小專欄,其中《2018 年將至,ios 工程師如何自我提高》這篇文章使我感觸頗深,最近剛好開始看python, 就萌生了寫一個(gè)python腳本練練手的想法。

1. 為什么要寫這個(gè)app?

原因之一當(dāng)然是學(xué)了點(diǎn)東西總想練練手。
更為重要的原因則是,在寫iOS app時(shí),每增加一個(gè)網(wǎng)絡(luò)請(qǐng)求,就要寫一個(gè)json對(duì)應(yīng)的model類,而構(gòu)造這些model類的代碼毫無快感可言。so,人生苦短,我用python



2. 技術(shù)棧

  • python最最最基礎(chǔ)知識(shí)

    1. json反序列化
      將輸入的json字符串轉(zhuǎn)成對(duì)應(yīng)的字典(dict) + 數(shù)組(list)組合的形式
    res = json.loads("輸入的json字符串")
    
    1. 字符串操作
      解析字典和數(shù)組內(nèi)容,生成swift對(duì)應(yīng)的字符串,拼接起來即可
      # 遍歷字典
      for (key, value) in dic.items():
    
      # 轉(zhuǎn)換成swift格式
      if isinstance(value, str):
          return "String"
      elif isinstance(value, float):
          return "Float"
    
      # 字符串?dāng)?shù)組拼接
      result= ''.join([line+'\n' for line in res])
    

    推薦兩個(gè)不錯(cuò)學(xué)習(xí)資源:Python 簡(jiǎn)單入門指北(試讀)Python教程- 廖雪峰

  • Cocoa APP生成

  1. 界面搭建
    Mac OS的界面搭建和iOS超級(jí)相似,如果會(huì)iOS編程,3分鐘就能搞定,這里不做贅述。
  1. 圖標(biāo)生成
    制作一個(gè)1024*1024的圖片,我習(xí)慣使用pixelmator,個(gè)人感覺比較簡(jiǎn)單上手,然后生成若干張對(duì)應(yīng)尺寸的圖標(biāo),這種app有很多,我用的是Prepo
  1. Cocoa 運(yùn)行python腳本
    NSTask已經(jīng)被廢棄,應(yīng)該使用Process()執(zhí)行腳本文件
let buildTask = Process()
let outPip = Pipe()
let errorPipe = Pipe()

buildTask.launchPath = "/usr/bin/python"
// arguments是[String]類型,第一個(gè)元素應(yīng)該為xx.py的路徑,后面元素為該py接受的參數(shù)
buildTask.arguments = args
buildTask.standardInput = Pipe()
buildTask.standardOutput = outPip
buildTask.standardError = errorPipe
// 腳本執(zhí)行完畢后的回調(diào)
buildTask.terminationHandler = { p in
      self.taskFinish()
}
buildTask.launch()
buildTask.waitUntilExit()

// 腳本的輸出結(jié)果,即腳本文件的print()方法打印的內(nèi)容
let data = outPip.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: String.Encoding.utf8)
        
// 錯(cuò)誤處理, python系統(tǒng)錯(cuò)誤
let errorData = errorPipe.fileHandleForReading.readDataToEndOfFile()
let errorStr = String(data: errorData, encoding: String.Encoding.utf8)
if let aError = errorStr, aError != "" {
    sendError("解析錯(cuò)誤\r\n" + aError)
}
  • arguments:腳本參數(shù)

let scripyPath = Bundle.main.path(forResource: "Parse", ofType: "py")! // 腳本路徑
let para1 = "input info" // 傳入?yún)?shù),通過sys.argv[I]獲取
let args = [scripyPath, para1]
buildTask.arguments = args

  • standardOutput:腳本輸出

執(zhí)行腳本后可通過output獲取結(jié)果
注意:腳本的返回結(jié)果不是通過函數(shù)的return,而是通過調(diào)用print(infos)函數(shù),即infos作為結(jié)果返回
let data = outPip.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: String.Encoding.utf8)

  • standardError: 錯(cuò)誤輸出

解決python的exception信息
task.terminationStatus 不等于0也能判斷為失敗


3. 封裝

Cocoa 運(yùn)行python腳本的代碼,寫起來雖然不算特別麻煩,但總也說不是簡(jiǎn)潔,于是重新封裝了一個(gè)類方便調(diào)用:CocoaPython
使用如下:

let script = CocoaPython(scrPath: pyPath)
script.runAsync()

詳細(xì)說明:

// python腳本文件路徑
guard let aPath = Bundle.main.path(forResource: "Parse", ofType: "py") else { return }

// args: py文件接受的參數(shù)列表,通過sys.argv[i]訪問
// block: 完成后的回調(diào),包括返回值和錯(cuò)誤內(nèi)容
let script = CocoaPython(scrPath: aPath, args: [""]) { [weak self] in
    print($0) // 返回值,所有的py中print()的內(nèi)容
    print($1) // py中的錯(cuò)誤信息
}

script.spliPara = "$" // 如果有多個(gè)結(jié)果,每個(gè)結(jié)果之間的分隔符,不設(shè)置則將所有的結(jié)果當(dāng)成一個(gè)結(jié)果返回,即result == result[0]
script.runAsync() // 異步執(zhí)行,回調(diào)在異步主線程中調(diào)用
// or script.runAsync(asyncComlete: false) // 異步執(zhí)行,回調(diào)在global中執(zhí)行
// or script.runSync() // 同步執(zhí)行

4. 資源

github地址: json2swift
OS X app: json2Swift.app
python 腳本: json2Swift.py

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

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

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