從零開始 編寫一個 XCode Source Extension

從零開始 編寫一個 XCode Source Extension

先看最終效果圖:

demo-tuya.gif

簡書圖片大小限制躁劣,不清楚可以點擊查看原圖

就像你看到的促煮,這個插件包括兩個模塊,一個是設置頁面我們使用Mac APP 完成(不需要Mac開發(fā)基礎)整袁,另一部分是Xcode source Editor插件菠齿。這兩個模塊我們均用swift進行開發(fā)。

第一步:開始創(chuàng)建項目坐昙,創(chuàng)建一個Mac APP

001.png

然后為項目取名為DKJSONExtension開發(fā)語言為swift使用storyboard绳匀。
這時候我們就創(chuàng)建好了主項目了,運行以后是一個空白的窗口炸客。我們先實現(xiàn)設置功能的頁面疾棵,在進行xcode source editer插件的開發(fā)。首先我們打開storyboard
修改一下主程序窗口的標題
002.png

接著在viewcontroller中拖出設置頁面痹仙,為了方便布局我使用兩個stackview去橫向排列3個選項
003.png

設置界面完成以后就可以進行事件處理了是尔,設置頁面主要是為了顯示和修改當前的模型類型和命名規(guī)則。這里我們使用UserDefaults存儲數(shù)據(jù)
為了和storyboard中的控件交互這里我們使用兩種常用的方式獲取控件第一種使用@IBOutlet 引用开仰,第二章通過設置tag取subview
004.png

我們要實現(xiàn)單選按鈕需要在按鈕的點擊事件中自己處理.為同一行的按鈕做一個事件處理拟枚,并且存儲當前的值

@IBAction func modeTypeChange(_ sender: NSButton) {
        [codeableBtn,handyJSONBtn,swiftyJSONBtn].forEach {
            $0?.state = sender.title == $0?.title ? .on : .off
        }
        UserDefaults.modelType = sender.title 
    }

    @IBAction func modeNameStyleChange(_ sender: NSButton) {
        for i in 0..<3 {
            let btn = self.view.viewWithTag(100 + i) as? NSButton
            btn?.state = sender.title == btn?.title ?.on:.off
        }
        UserDefaults.modelStyle = sender.title
    }

這樣我們做好了事件處理和數(shù)據(jù)存儲,這里我們存儲數(shù)據(jù)需要和extension共享為此我們使用APP group進行userdefault 存取众弓。如果使用UserDefaults.standard進行存取我們將無法在extension中獲取到存取的值恩溅。
具體步驟如下:
到開發(fā)者中心創(chuàng)建APP group

005.png

選擇 APPgroup 填寫名稱和標識
創(chuàng)建完成打開
如圖復制identifier
006.png

在項目中添加APPgroup,天上剛才復制的identifier
007.png

這時我們就能按group存取數(shù)據(jù)了,這些數(shù)據(jù)將會被同一group的應用共享谓娃。我們?yōu)閡serdefault 添加擴展.注意要使用groupID創(chuàng)建userdefault


extension UserDefaults{
    static var grouped:UserDefaults{
        return UserDefaults(suiteName: "group.com.dkjone.DKJsonExtension") ?? standard
    }
    /// 模型類型
    static var  modelType: String {
        get { return grouped.string(forKey: #function) ?? "HandyJSON" }
        set { grouped.setValue(newValue, forKey: #function) }
    }
    // 命名規(guī)則
    static var modelStyle: String {
        get { return grouped.string(forKey: #function) ?? "駝峰法" }
        set { grouped.setValue(newValue, forKey: #function) }
    }
}

最后一步脚乡,設置頁面加載時,顯示當前存儲的設置數(shù)據(jù)

 override func viewDidLoad() {
        super.viewDidLoad()
        [codeableBtn,handyJSONBtn,swiftyJSONBtn].forEach {
            $0?.state = UserDefaults.modelType == $0?.title ? .on : .off
        }
        for i in 0..<3 {
            let btn = self.view.viewWithTag(100 + i) as? NSButton
            btn?.state = UserDefaults.modelStyle == btn?.title ?.on:.off
        }
    }

到此我們完成了設置應用的全部功能
接下來我們實現(xiàn)source editor extension部分
這部分我們首先創(chuàng)建extension如圖:


008.png

創(chuàng)建完成以后我們項目中多呢以下文件

-- JSONExtension
---- SourceEditorExtension.swift
---- SourceEditorCommand.swift
---- Info.plist

這幾個文件是我們編寫extension的關鍵滨达。我們的 項目 target也會多一個選項,我們使用如下選項運行就會出現(xiàn)一個灰色的xcode 可以讓我們調試奶稠,用灰色xcode 打開文件便會在editor菜單中出現(xiàn)我們添加的插件名稱。


009.png

如果你出現(xiàn)報錯

dyld: Library not loaded: @rpath/XcodeKit.framework/Versions/A/XcodeKit
  Referenced from: 

說明庫連接有問題弦悉,找到這個庫鏈接刪除后按圖添加即可


010.png

出現(xiàn)以下錯誤是賬號問題需要到xcoed->preferencces->account 中窒典,刪除之前的賬號,重新登陸賬號就可以了

"Your session has expired. Please log in."

如果成功運行會出現(xiàn)灰色Xcode

011.png

012.png

用灰色的xcode打開文件或者項目在editor 菜單最下面就會有我們新建的插件了稽莉,在此之前我們修改下插件的菜單名稱
可以在info.plist中修改也可以在代碼中自定義瀑志,我們直接修改代碼中的返回值,修改返回值優(yōu)先級高于info.plist,
修改SourceEditorExtension.swift文件為以下內容

class SourceEditorExtension: NSObject, XCSourceEditorExtension {
    var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: Any]] {
        return [[.nameKey: "將JSON文件轉化模型", .identifierKey: "paraseFile", .classNameKey: SourceEditorCommand.className()],
                [.nameKey: "從剪貼板獲取JSON轉化為模型", .identifierKey: "parasePasteboard", .classNameKey: SourceEditorCommand.className()]]
    }
}

要注意的地方:

nameKey: 菜單的名稱
identifierKey: 菜單的標識污秆,可以在處理類中用于判斷點擊了哪一個菜單
classNameKey: 處理此菜單的類名劈猪,這里我們直接使用className()獲取,如果你直接寫字符串記得在類名前加上模塊名良拼。

到此我們直接運行后就是以下的效果了


013.png

最后我們需要處理如何生成代碼了:
打開處理類

class SourceEditorCommand: NSObject, XCSourceEditorCommand {
// 點擊菜單時調用的方法
 func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) {
 }
}

這里方法的參數(shù)invocation就是當前編輯的上下文可以獲取當前菜單的ID和當前文檔類型战得,文檔內容,所在行號等等庸推。
如果需要修改文件內容直接修改invocation.buffer.lines就可以常侦。這是個[Sting]類型的可變數(shù)組浇冰,可以在后面直接加,也可以替換某一行內容聋亡。
為了獲取主程序保存的配置我們也要為這個extension配置相同的APP group肘习,方法同上。也使用相同的userdefault就可以取出主程序存儲的配置了坡倔。

這里具體解析json的邏輯就不仔細說明了漂佩,有興趣的可查看完整的源碼github或者碼云

最后一步發(fā)布我們制作的插件。選擇主項目罪塔,然后xcode->product->archive 接下來和發(fā)布IOS應用一樣可以選擇開發(fā)者簽名或者提交到APP store 或者內部測試投蝉。導出內容如圖:

014.png

如果想制作圖中的dmg文件,打開磁盤工具->文件->新建映像->基于文件夾新建->選擇插件所在文件夾即可征堪。使用時將其中的APP文件(上圖圈中的)拖入application文件夾后打開瘩缆。記得一定要打開一次,然后到系統(tǒng)偏好設置->擴展中勾選這個插件就可以了
015.png

這樣我們就可以正常使用這個extension了

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末请契,一起剝皮案震驚了整個濱河市咳榜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌爽锥,老刑警劉巖涌韩,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異氯夷,居然都是意外死亡臣樱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門腮考,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雇毫,“玉大人,你說我怎么就攤上這事踩蔚∨锓牛” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵馅闽,是天一觀的道長飘蚯。 經(jīng)常有香客問我,道長福也,這世上最難降的妖魔是什么局骤? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮暴凑,結果婚禮上峦甩,老公的妹妹穿的比我還像新娘。我一直安慰自己现喳,他們只是感情好凯傲,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布犬辰。 她就那樣靜靜地躺著,像睡著了一般泣洞。 火紅的嫁衣襯著肌膚如雪忧风。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天球凰,我揣著相機與錄音,去河邊找鬼腿宰。 笑死呕诉,一個胖子當著我的面吹牛,可吹牛的內容都是我干的吃度。 我是一名探鬼主播甩挫,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼椿每!你這毒婦竟也來了伊者?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤间护,失蹤者是張志新(化名)和其女友劉穎亦渗,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體汁尺,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡法精,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了痴突。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搂蜓。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖辽装,靈堂內的尸體忽然破棺而出帮碰,到底是詐尸還是另有隱情,我是刑警寧澤拾积,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布殉挽,位于F島的核電站,受9級特大地震影響殷勘,放射性物質發(fā)生泄漏此再。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一玲销、第九天 我趴在偏房一處隱蔽的房頂上張望输拇。 院中可真熱鬧,春花似錦贤斜、人聲如沸策吠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽猴抹。三九已至带族,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蟀给,已是汗流浹背蝙砌。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留跋理,地道東北人择克。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像前普,于是被迫代替她去往敵國和親肚邢。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內容