詳解一步步實現(xiàn)Xcode 8 插件——Source Editor Extensions

O. 背景

Xcode 8前,開發(fā)者可以通過運行時注入代碼來實現(xiàn)添加插件,甚至在著名的插件管理工具Alcatraz上提交和分發(fā)插件。但是,Xcode 8成為這種開始方式的終結者,因為它提供了自家的Xcode Source Editor Extension方式開發(fā)插件。
接下來,你將了解到:

  • 如何創(chuàng)建Xcode Source Editor Extension(插件)
  • 如何測試插件
  • 如何快速進行插件開發(fā)
  • 開發(fā)完成后如何讓小伙伴們使用
  • 插件的優(yōu)勢和局限

一. 著手創(chuàng)建插件

1. 首先,創(chuàng)建一個macOS下的Cocoa Application工程,作為插件的母體:

2. 設置工程參數(shù),完成工程創(chuàng)建。

這里工程名: SourceEditorExtensionDemo 語言: Swift

3. 添加Target

選擇Xcode Souce Editor Extension:

配置Target名稱等信息,F(xiàn)inish完成設置:

此時彈出是否啟用此Target的Scheme對話框,點擊Activate按鈕啟用:

4. 文件結構

二. 測試插件

1. 配置簽名(不配置的后果是,測試時不顯示插件按鈕)

配置好簽名后,兩個Target: SourceEditorExtensionDemo 和 MyPlugin 的簽名(Siging)要一致,如圖:


2. 運行插件

點擊左側運行按鈕 或者 Command + R運行插件,彈出下面的對話框,選擇Xcode(如果有多個Xcode,選擇Xcode 8以上的版本),并點擊Run按鈕:

然后Dock中出現(xiàn)一個黑色的東東,沒錯,黑色的Xcode:

雙擊右側的一個工程,就可以假裝把插件安裝到Xcode里,進行插件調試了(插件按鈕放在Editor最下面):

(關于插件,因為我們啥都沒寫,所以點擊插件按鈕暫時啥也沒有 = =)

三. 認識并開發(fā)插件

1. 插件相關文件

  • SourceEditorExtension.swift 和插件的生命周期和配置有關,實現(xiàn)了XCSourceEditorExtension協(xié)議中的一個方法extensionDidFinishLaunching() 和一個變量commandDefinitions,默認是被注釋掉的。

  • 方法extensionDidFinishLaunching()是指剛剛加載好插件但還未點擊插件按鈕時,可以執(zhí)行某些準備工作。

  • 變量commandDefinitions返回字典類型的數(shù)組,可以為每個插件重寫名字、標識符和自定義類名等信息,相當于設置后面要介紹的的Info.plist文件中對應的XCSourceEditorCommandName、XCSourceEditorCommandIdentifierXCSourceEditorCommandClassName信息。

    SourceEditorExtension.swift

  • SourceEditorCommand.swift 實現(xiàn)了XCSourceEditorCommand協(xié)議中的perform方法,點擊插件按鈕所執(zhí)行的具體邏輯就是在這個方法中完成的,因此是實現(xiàn)插件功能的核心。

    SourceEditorCommand.swift

  • Info.plist 其中,每個插件的名字、標識符和自定義類名分別對應XCSourceEditorCommandName、XCSourceEditorCommandIdentifierXCSourceEditorCommandClassName信息。 XCSourceEditorExtensionPrincipalClass對應插件的默認實現(xiàn)類:SourceEditorExtension.swift。

    Info.plist

2. 制作一個簡單的插件

在SourceEditorCommand.swift文件中書寫如下代碼:

class SourceEditorCommand: NSObject, XCSourceEditorCommand {
    
    func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void {
        // Implement your command here, invoking the completion handler when done. Pass it nil on success, and an NSError on failure.
        
        // 第一個選中區(qū)域
        let firstSelectObject: XCSourceTextRange = invocation.buffer.selections.firstObject as! XCSourceTextRange
        // 開始刪除的位置
        let start = firstSelectObject.start.line
        // 要刪除的行數(shù)
        let end = firstSelectObject.end.line
        // 設置刪除的范圍
        let deleteRange = IndexSet(integersIn: start...end)
        // 刪除對應行的代碼
        invocation.buffer.lines.removeObjects(at: deleteRange)
        
        completionHandler(nil)
    }
}

然后運行插件,即可通過插件按鈕實現(xiàn)對選中的代碼進行整行刪除。

原理分析:

  • 插件一旦運行起來 -> 立即調用SourceEditorExtension.swift中的 extensionDidFinishLaunching() 方法做準備工作 -> 同時檢查是否自定義 commandDefinitions 變量,以確定實現(xiàn)插件的類名、插件名字和唯一標識符信息 -> 如果沒有自定義此變量,直接讀取 Info.plist 文件中的配置。
  • 點擊插件中的按鈕 -> 直接執(zhí)行我們自定義的或者 Info.plist 中 XCSourceEditorCommandClassName 對應的類文件中的 perform 方法,該方法中的參數(shù)invocationXCSourceEditorCommandInvocation類型,包含我們點擊的插件的唯一標識符屬性,以及我們在點擊插件前光標選中的區(qū)域等信息。
  • XCSourceEditorCommandInvocation有個XCSourceTextBuffer類型的buffer屬性,此類型有兩個比較常用的屬性linesselections,分別代表我們點擊插件前光標所在文件的所有行 和 光標選中的區(qū)域。
  • 多個插件可以對應一個類實現(xiàn)文件,在代碼中,用唯一標識符來區(qū)分不同的插件。

四. 讓插件及時傳播給小伙伴們使用

開發(fā)時,插件只要運行起來,我們就可以在Xcode菜單欄中的Editor最下面看到插件名字和使用,但一旦停止運行,插件并不會常駐Xcode供我們使用。
但是,我們可以這樣做: 找到Products文件夾下生成的的.app文件

右鍵點擊此文件 -> “在Finder中顯示” -> 將這個.app文件拷貝到你或者小伙伴電腦上的"應用程序"里 :

在“應用程序”中雙擊.app文件運行。然后,打開“系統(tǒng)偏好設置” -> "擴展" -> "Xcode Source Editor" -> 確認插件名字前已打鉤 -> 此時Xcode中菜單欄Editor下的插件雖然顯示,但是為灰色,無法點按,所以要 -> 重啟Xcode -> 大功告成!

我們也可以為插件添加快捷鍵: Xcode -> "Preferences" -> "Key Bindings" -> 搜索插件名字 -> 添加對應的快捷鍵:


五. 優(yōu)缺點總結

優(yōu):

  • 支持上架到Mac App Store
  • 每個Extension運行在獨立的進程,如果它出了事故,不會引起Xcode的崩潰
  • 可以分配快捷鍵

:

  • 無UI相關接口
  • 只能做文本相關處理

總之: 第一版插件 too young too simple,但我們要對蘋果心懷期待,假裝未來很美好~

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

相關閱讀更多精彩內容

友情鏈接更多精彩內容