Xcode8 開放了新的一個Extension:Xcode Source Editor Extension,可以讓我們自己開發(fā)Xcode 插件,但是目前開發(fā)的API 還比較少,但是也不妨礙我們了解和使用。本文主要介紹如何使用Xcode Source Editor Extension 實現(xiàn)一個簡單的自動生成代碼的插件。
效果

實現(xiàn)
新建一個MacOS 宿主項目,再新建一個Target,類型為Xcode Source Editor Extension,并且設(shè)置target的簽名和宿主App的簽名一致。


目錄結(jié)構(gòu)

系統(tǒng)默認(rèn)為我們生成SourceEditorCommand 文件,其中這個方法就當(dāng)做主入口,當(dāng)調(diào)用插件時會執(zhí)行這個方法。但是只能獲取到當(dāng)前編輯文件的內(nèi)容,不能獲取整個工程。
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.
if invocation.commandIdentifier == InsetCodeKey {
handleInsertCode(invocation: invocation)
}else{
NSWorkspace.shared.open(URL.init(fileURLWithPath: "/Applications/GenerateCode.app"))
}
completionHandler(nil)
}
核心代碼如下,大致邏輯是獲取當(dāng)前輸入的key,根據(jù)提前錄入的Map,查找對應(yīng)Value,并且替換當(dāng)前行內(nèi)容。
func handleInsertCode(invocation: XCSourceEditorCommandInvocation){
let selection = invocation.buffer.selections.firstObject as! XCSourceTextRange
let totalLines = invocation.buffer.lines
let curIndex = selection.start.line
var curLineContent = totalLines[curIndex] as! String
let mapKey = curLineContent.trimmingCharacters(in: .whitespacesAndNewlines)
let map = SharedUserDefault.shared.mapping
if let value = map[mapKey] {
let arr = convertToLines(string: value)
var numberOfSpaceIndent = curLineContent.range(of: mapKey)!.lowerBound.encodedOffset
var indentStr = ""
while numberOfSpaceIndent > 0 {
indentStr = indentStr.appending(" ")
numberOfSpaceIndent -= 1
}
if arr.isEmpty{
return
}
if let range = curLineContent.range(of: mapKey){
curLineContent.replaceSubrange(range, with: arr[0])
totalLines[curIndex] = curLineContent
}
for i in 1..<arr.count{
let insetStr = indentStr + arr[i]
totalLines.insert(insetStr, at: curIndex + i)
}
}
}
錄入界面

在主工程中,創(chuàng)建錄入界面,整體是個NSTableView,展示保存好的Map,雙擊某一行或者點擊添加按鈕,進(jìn)入編輯頁面,主要用NSTextField 實現(xiàn)

全局保存的Map 存儲在UserDefaults 里,但是宿主和擴(kuò)展共享數(shù)據(jù)的話,需要suiteName 相同才行,需要在App Group 里設(shè)置相同的key。
測試
先運(yùn)行主App,測試添加數(shù)據(jù)是否正常
運(yùn)行插件,選擇Xcode,會出來一個灰色的Xcode,隨便打開一個項目

輸入key,運(yùn)行插件,正確生成代碼。

也可以綁定快鍵鍵

使用

將app 拷入應(yīng)用程序里,并且將設(shè)置里Xcode 擴(kuò)展選上,重啟Xcode,就能在Editor 里使用啦

總結(jié)
插件主要參考了EasyCode,站在了巨人的肩膀上。但是目前EasyCode 好像Swift 不能用,因為媳婦開發(fā)用的純Swift,所以主要寫給她用的,目前插件的功能還很簡單,但是基本可以使用了,后續(xù)可以繼續(xù)優(yōu)化!