Xcode插件开发

4,062 阅读2分钟

简介

创建一个插件的过程并不复杂,只是 官方教程 过于简单,所以基于它补充细节,以及遇到的坑。

创建插件

环境:Xcode12.5.1

先创建一个 Mac App

20210726-1158.png

20210726-1209.png

然后 Target 里添加一个 extension

20210726-1210.png

20210726-1211.png

这里可能需要重新引用下,否则在 Xcode 中,会找不到该插件

20210726-1212.png

添加代码

class SourceEditorCommand: NSObject, XCSourceEditorCommand {
    func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void {
        // 当前文件每一行内容
        let lines = invocation.buffer.lines
        // Reverse the order of the lines in a copy.
        let updatedText = Array(lines.reversed())
        lines.removeAllObjects()
        lines.addObjects(from: updatedText)
        // 回调
        completionHandler(nil)
    }
}

调试插件时,选好开发者团队进行签名,即使资格过期也可以

20210727-1130.png

20210727-1220.png

打包比较简单:

  • Product -> Archive
  • Window -> Organizer -> Distribute App

20210727-1215.png

最后一个不建议使用,经常需要重新签名。

代码怎么写?

一般处理逻辑:获取选中的内容 -> 处理 -> 添加到原文

简单代码如下

class SourceEditorCommand: NSObject, XCSourceEditorCommand {
    func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void {
        // 整个文件所有信息
        let buffer = invocation.buffer
        let lines = buffer.lines

        // 获取选中的内容
        var selections = [String]()
        var selectionRanges = [NSRange]()
        for r in buffer.selections {
            guard let end = (r as AnyObject).end else {
                continue
            }

            let startLine = (r as AnyObject).start.line
            let endLine = end.column > 0 ? end.line + 1 : end.line

            for i in startLine ..< endLine {
                guard let s = lines[i] as? String else {
                    continue
                }
                selections.append(s)
            }
            // 记录选中的范围
            selectionRanges.append(NSRange(location: startLine, length: selections.count))
        }

        // 对应 Info.plist 中的 XCSourceEditorCommandIdentifier
        let id = invocation.commandIdentifier

        // 根据 id 区分操作,修改内容,则直接操作 lines 即可

        // 回调
        completionHandler(nil)
    }
}

常见问题

在 XcodeEditor 中找不到该插件。

重新引用下 Extension 的 lib,如下图

20210715-1103.png

另外,有可能是签名问题,需要使用开发者证书,Xcode 控制台里有详细的提示。

IDEExtensionManager: Xcode Extension does not meet code signing requirement

「扩展」里找不到添加的插件。

大概率是电脑上存在多个 Xcode,导致插件无法正常加载。 解决办法

$ PATH=/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support:"$PATH"
$ lsregister -f /Applications/Xcode.app

Xcode 里显示的按钮灰色

20210719-1640.png

调试异常

20210720-2105.png

若已经安装了该插件,调试时,版本号需要高于原先的。

更多插件

PS:很多插件没有支持新版的 Xcode,需要重新引用下 SDK,再打包下。

ugc / HTSXCTool · GitLab

theswiftdev/awesome-xcode-extensions: Awesome native Xcode extensions.

5 Xcode Extensions You Must Have | Better Programming

参考资料

初涉 Xcode 插件开发 | David'Blog

Xcode - Source Editor Extension

XcodeKit and Xcode Source Editor Extensions - NSHipster

Xcode Source Editor Extension 创建入门 - 简书