Xcode Source Editor Extension

不知道是不是受xcodeghost的影响,现在任何library和bundle都需要Xcode8认证许可,通过注入code实现第三方功能的plugin也不允许在Xcode8上使用。取而代之的,Apple提供了一种新技术,通过为Xcode开发扩展,获取并改变开发环境,从而实现类似plugin的功能。这个技术就是Xcode Source Editor Extension(以下简称xsee)。
要指出的是,xsee虽然打开了一条新道路,但作为新技术,目前仍然是不成熟并且功能也很有限。

  • xsee只能获取和修改source code,并不能像很多功能强大的插件,对整个工程作出修改。
  • 本质是extension,必须依存于MacOS app
  • 没有自己单独的UI interface
  • 只能通过Xcode command方式触发

不过既然提供了一种新技术,想必Apple也会在这个方向上有所深入,未来应该会提供更多更全面的功能。

Demo: 类似VVDocumenter为方法添加注释

以下通过实现一个类似VVDocumenter的demo,来介绍如何创建使用xsee。

  1. 新建MacOS app
    xsee本质是mac extension,所以需要新建一个MacOS app。


    Xcode Source Editor Extension_第1张图片
    create MacOS app.png
  2. 创建extension
    file -> new -> target 创建Xcode Source Editor Extension


    Xcode Source Editor Extension_第2张图片
    create xsee.png
  3. 设置并运行
    编辑extension的scheme,设置executable为Xcode.app,即mac上安装的Xcode8。


    Xcode Source Editor Extension_第3张图片
    set extension.png

    运行extension,就会生成一个自定义Xcode环境,在菜单栏的Editor下,可以看到一个新的command,点击该command会触发扩展功能。


    Xcode Source Editor Extension_第4张图片
    customer xcode.png
  4. 分析code structure
    新建的extension结构很简单,默认创建几个文件:

Info.plist
SourceEditorCommand.h
SourceEditorCommand.m
SourceEditorExtension.h
SourceEditorExtension.m

SourceEditorExtension中定义了extension的life cycle,虽然只有一个launch 函数。command信息无需在commandDefinitions中设定,可以直接到info.plist中设置:

NSExtension
 
  NSExtensionAttributes
  
   XCSourceEditorCommandDefinitions
   
    
     XCSourceEditorCommandClassName
     SourceEditorCommand
     XCSourceEditorCommandIdentifier
     HAC.addDocuments
     XCSourceEditorCommandName
     Sakura
    
   
   XCSourceEditorExtensionPrincipalClass
   SourceEditorExtension
  
  NSExtensionPointIdentifier
  com.apple.dt.Xcode.extension.source-editor
 

SourceEditorCommand中定义了command触发的回调函数,具体的处理逻辑放在

- (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);
}

方法传入的参数XCSourceEditorCommandInvocation即保存着当前source code的所有信息,最重要的是identifier和buffer,前者即定义在info.plist中的command id,做区分;buffer即缓存的环境信息,不过目前信息很少,重要的一个是lines一个是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  *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  *selections;

lines是source code的行信息,selection是当前选中区域。然后就没了...
所以整个流程很简单:

  • 启动extension,回调extensionDidFinishLaunching
  • 菜单或快捷键触发command
  • 拦截command,调用performCommandWithInvocation
  • 获取当前环境信息XCSourceEditorCommandInvocation,处理并回塞数据到buffer
  • 刷新Xcode环境

在本demo中,逻辑很简单:

  • 取得当前选中区后面的文本
  • 遍历匹配最接近的一个方法
  • 正则表达式解析出方法名,返回类型,参数
  • 生成注释信息
  • 将注释信息回塞到选中区后一行。

tips

如果在OS 10.11上运行,可能需要运行命令:

sudo /usr/libexec/xpccachectl 

并且在 Xcode 尝试加载扩展之前重启。这是因为安装新的 SDK 以及 El Capitan 的 XPC 服务不允许这样的操作。
参考资料时,很多人反映extension性能还很不稳定。目前在Xcode8正式版本上,感觉还是很可靠的,当然目前只是初步体验,demo很简单。

参考链接:
How to Create an Xcode Source Editor Extension

你可能感兴趣的:(Xcode Source Editor Extension)