Sketchプラグインの開発環境をXcodeで構築する


Xcode用テンプレートのインストール

SketchプラグインのためのXcodeテンプレートが存在するので、それを利用します。

$ git clone https://github.com/MagicSketch/XcodeTemplate-SketchPlugin.git ~/Library/Developer/Xcode/Templates/Sketch\ Plugin

新規プロジェクト作成

テンプレートには3種類あります。

  • Sketch Panel UI Framework
    • インスペクターのUIを提供するにはこのテンプレからフレームワーク作成します
  • Sketch Plugin Framework
    • 独自のフレームワークを作成する場合にはこのテンプレからフレームワークを作成します
  • Sketch Plugin Bundle
    • Sketchプラグインバンドルのテンプレです。今回はこれを利用します

manifest.json

manifest.json はプラグインの情報を記述するためのJSONファイルです。

新規プロジェクトからすでにプラグインの雛形は出来上がっているので、manifest.jsonに必要な情報を記述しておきます。

項目 内容
name プラグインの表示名
description プラグインの説明文(プラグインマネージャ画面に表示されます)
author 作者名
authorEmail 作者メール
homepage プラグインホームページ
identifier プラグインID(逆ドメイン記法が望ましい)
compatibleVersion Sketch互換バージョン(44など/現在は利用されていない模様)
build プラグインビルド番号
version プラグインバージョン
appcast アップデート配信対応用
menu プラグインメニューの定義
commands プラグインメニューコマンドの定義

menu定義

Pluginsメニューに挿入するメニュー項目を定義できます。
サブメニューにまとめるなら isRootfalse にします。そのとき、title がメニュー名になります。
items には commands で定義するコマンドの identifier を記述します。

menu例
"menu": {
    "isRoot" : false,
    "shortcut" : "",
    "title": "LoveCocoa",
    "items": [
        "menu-1"
    ]
}

commands定義

命令を定義します。コマンドの identifier とスクリプトのメソッド名を対応付けます。
name で表示名を設定します。
script でスクリプトのファイル名を指定します。
handler handlers で実行するメソッド名を指定します。

commands例
"commands": [
    {
        "name" : "Run",
        "identifier" : "menu-1",
        "shortcut" : "",
        "script" : "script.cocoascript",
        "handler" : "onRun"
    },
    {
        "script" : "script.cocoscript",
        "handlers" : {
            "actions" : {
                "Startup" : "onStartup",
                "OpenDocument":"onOpenDocument",
                "SelectionChanged.finish" : "onSelectionChanged"
            }
        }
    }
]

CocoaScript

JavaScriptでCocoa/Objective-Cをブリッジできます。
直接Objective-Cメッセージを記述してCocoa APIを呼び出すことができます。

※テンプレで自動生成されるスクリプトファイルは .cocoscript となっており、これはタイポだと思われます。プルリクが出ていますが今のところマージされていません。
https://github.com/MagicSketch/XcodeTemplate-SketchPlugin/pull/7

Xcodeワークスペース

例として二つのプロジェクトを同時に扱う場合を想定します。

  • Sketchプラグイン: Sketchプラグインのプロジェクト
  • Cocoa Bundle: プラグインに動的にロードさせるバンドルのプロジェクト

まずは空のワークスペースを用意しましょう。

Sketchプラグイン

テンプレからSketchプラグインのプロジェクトを新規作成します。
これを先ほどのワークスペースに追加します。

Cocoa Bundleでプロジェクトを作成

macOSのCocoa Bundleでプロジェクトを作成します。
これを先ほどのワークスペースに追加します。

Sketchプラグイン: ビルドフェーズ

Sketchプラグイン側のターゲットからBuild Phasesを開き、次の手順を踏みます。

サブプロジェクトの紐付け

"Link Binaries with Libraries" にCocoa Bundleプロジェクトファイル(xcodeproj)を追加します。

Target Dependencies の紐付け

+ボタンから成果物(.bundle)を指定します。

.bundle のコピー設定

Copy Files に .bundle を追加します。

Sketchプラグイン: プラグインの自動インストール (Run Script)

ビルド済みプラグインをPluginsディレクトリーにコピーするためのスクリプトがテンプレに実装されているため、我々はただXcodeでビルドして実行するだけで良いです。

Sketchプラグイン: Sketch.appの起動設定

ビルド&実行と同時にSketch.appを立ち上げてプラグインをロードさせることができます。
Sketchプラグイン側のスキーム設定を開き、ExecutableにSketch.appを指定します。

コンソールもXcodeのものが使えるので便利です。

Cocoa Bundle: プリンシパルクラスの用意

プリンシパルクラスを用意します。名前を Principal としたとき、これを Info.plist に記述しておきます。(名前はなんでも良いです。)

Principal.h
#import <Cocoa/Cocoa.h>

@interface Principal : NSObject

+ (NSString*)hello;
- (NSString*)goodbye;
- (NSString*)show;

@end
Principal.m
#import "Principal.h"
#import "BundleTest-Swift.h"

@implementation Principal

+ (NSString*)hello {
    return @"hello";
}

- (NSString*)goodbye {
    return @"byebye";
}

- (NSString*)show {
    return @"show";
}

@end

注意

Swift コードを含んでいる場合に Library not loaded: @rpath/libswiftAppKit.dylib が出てしまう

Build Settingsから Runpath Search Paths${DT_TOOLCHAIN_DIR}/usr/lib/swift/macosx/ を追加するとこれは直ります。

Cocoa Bundleやフレームワークは一度ロードされると解放されないので注意

適宜XcodeのビルドキャッシュをクリアしてSketch.appも再起動しましょう。

参考資料

https://blog.magicsketch.io/beginning-sketch-plugins-development-in-xcode-2ee562352798
https://blog.magicsketch.io/sketch-plugin-xcode-template-c8236a6f7fff