不知道是不是受xcodeghost的影響,現(xiàn)在任何library和bundle都需要Xcode8認(rèn)證許可烫映,通過注入code實(shí)現(xiàn)第三方功能的plugin也不允許在Xcode8上使用叮称。取而代之的酣藻,Apple提供了一種新技術(shù),通過為Xcode開發(fā)擴(kuò)展程储,獲取并改變開發(fā)環(huán)境蹭沛,從而實(shí)現(xiàn)類似plugin的功能。這個(gè)技術(shù)就是Xcode Source Editor Extension(以下簡(jiǎn)稱xsee)章鲤。
要指出的是摊灭,xsee雖然打開了一條新道路,但作為新技術(shù)咏窿,目前仍然是不成熟并且功能也很有限斟或。
- xsee只能獲取和修改source code,并不能像很多功能強(qiáng)大的插件集嵌,對(duì)整個(gè)工程作出修改萝挤。
- 本質(zhì)是extension,必須依存于MacOS app
- 沒有自己?jiǎn)为?dú)的UI interface
- 只能通過Xcode command方式觸發(fā)
不過既然提供了一種新技術(shù)根欧,想必Apple也會(huì)在這個(gè)方向上有所深入怜珍,未來應(yīng)該會(huì)提供更多更全面的功能。
Demo: 類似VVDocumenter為方法添加注釋
以下通過實(shí)現(xiàn)一個(gè)類似VVDocumenter的demo凤粗,來介紹如何創(chuàng)建使用xsee酥泛。
-
新建MacOS app
xsee本質(zhì)是mac extension,所以需要新建一個(gè)MacOS app嫌拣。
create MacOS app.png -
創(chuàng)建extension
file -> new -> target 創(chuàng)建Xcode Source Editor Extension
create xsee.png -
設(shè)置并運(yùn)行
編輯extension的scheme柔袁,設(shè)置executable為Xcode.app,即mac上安裝的Xcode8异逐。
set extension.png
運(yùn)行extension捶索,就會(huì)生成一個(gè)自定義Xcode環(huán)境,在菜單欄的Editor下灰瞻,可以看到一個(gè)新的command腥例,點(diǎn)擊該command會(huì)觸發(fā)擴(kuò)展功能。
customer xcode.png 分析code structure
新建的extension結(jié)構(gòu)很簡(jiǎn)單酝润,默認(rèn)創(chuàng)建幾個(gè)文件:
Info.plist
SourceEditorCommand.h
SourceEditorCommand.m
SourceEditorExtension.h
SourceEditorExtension.m
SourceEditorExtension中定義了extension的life cycle燎竖,雖然只有一個(gè)launch 函數(shù)。command信息無需在commandDefinitions中設(shè)定要销,可以直接到info.plist中設(shè)置:
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>XCSourceEditorCommandDefinitions</key>
<array>
<dict>
<key>XCSourceEditorCommandClassName</key>
<string>SourceEditorCommand</string>
<key>XCSourceEditorCommandIdentifier</key>
<string>HAC.addDocuments</string>
<key>XCSourceEditorCommandName</key>
<string>Sakura</string>
</dict>
</array>
<key>XCSourceEditorExtensionPrincipalClass</key>
<string>SourceEditorExtension</string>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.dt.Xcode.extension.source-editor</string>
</dict>
SourceEditorCommand中定義了command觸發(fā)的回調(diào)函數(shù)构回,具體的處理邏輯放在
- (void)performCommandWithInvocation:(XCSourceEditorCommandInvocation *)invocation completionHandler:(void (^)(NSError * _Nullable nilOrError))completionHandler
{
// Implement your command here, invoking the completion handler when done. Pass it nil on success, and an NSError on failure.
[HACExtensionManager handleInvocation:invocation];
completionHandler(nil);
}
方法傳入的參數(shù)XCSourceEditorCommandInvocation即保存著當(dāng)前source code的所有信息,最重要的是identifier和buffer,前者即定義在info.plist中的command id捐凭,做區(qū)分拨扶;buffer即緩存的環(huán)境信息,不過目前信息很少茁肠,重要的一個(gè)是lines一個(gè)是section
/** The lines of text in the buffer, including line endings. Line breaks within a single buffer are expected to be consistent. Adding a "line" that itself contains line breaks will actually modify the array as well, changing its count, such that each line added is a separate element. */
@property (readonly, strong) NSMutableArray <NSString *> *lines;
/** The text selections in the buffer; an empty range represents an insertion point. Modifying the lines of text in the buffer will automatically update the selections to match. */
@property (readonly, strong) NSMutableArray <XCSourceTextRange *> *selections;
lines是source code的行信息,selection是當(dāng)前選中區(qū)域缩举。然后就沒了...
所以整個(gè)流程很簡(jiǎn)單:
- 啟動(dòng)extension垦梆,回調(diào)extensionDidFinishLaunching
- 菜單或快捷鍵觸發(fā)command
- 攔截command,調(diào)用performCommandWithInvocation
- 獲取當(dāng)前環(huán)境信息XCSourceEditorCommandInvocation仅孩,處理并回塞數(shù)據(jù)到buffer
- 刷新Xcode環(huán)境
在本demo中托猩,邏輯很簡(jiǎn)單:
- 取得當(dāng)前選中區(qū)后面的文本
- 遍歷匹配最接近的一個(gè)方法
- 正則表達(dá)式解析出方法名,返回類型辽慕,參數(shù)
- 生成注釋信息
- 將注釋信息回塞到選中區(qū)后一行京腥。
tips
如果在OS 10.11上運(yùn)行,可能需要運(yùn)行命令:
sudo /usr/libexec/xpccachectl
并且在 Xcode 嘗試加載擴(kuò)展之前重啟溅蛉。這是因?yàn)榘惭b新的 SDK 以及 El Capitan 的 XPC 服務(wù)不允許這樣的操作公浪。
參考資料時(shí),很多人反映extension性能還很不穩(wěn)定船侧。目前在Xcode8正式版本上欠气,感覺還是很可靠的,當(dāng)然目前只是初步體驗(yàn)镜撩,demo很簡(jiǎn)單预柒。