Septeni Engineer's Blog

セプテーニエンジニアが綴る技術ブログ

XcodeのメニューをカスタマイズするプラグインをSwiftで作る

こんにちは! 寺坂です

セミも鳴き始めてすっかり夏です

暑い日は自宅にこもってモクモクと開発するのもいいですね


と、いうことで、

今回はXcodeプラグイン開発の導入を書いていきたいと思います。

拙い部分も多いですが、どうか温かい目でよろしくお願いします!

プラグイン開発用のプロジェクト作成~ビルド成功まで

こちらを参考に、まずはプラグインのビルド+プラグイン読み込みまでを成功させましょう。

http://qiita.com/kgmyshin/items/c2e4e270a37882d3306a

基本的には、Objective-cと同様の設定を行います。

Swiftビルド用のライブラリを有効にする点など、

異なる部分もあるので丁寧に設定していきましょう。

また、今回使用するXcodeのバージョンは、6.4になります。

最初に呼ばれるクラス作成

下記のクラスメソッドを定義しておくと、そのクラスが呼ばれます。

class func pluginDidLoad(bundle: NSBundle)

さっそくクラスを作成していきます。

import Foundation

class MyPlugin: NSObject {

    class func pluginDidLoad(bundle: NSBundle) {
        NSLog("Hello world :)")
    }
}

ここまでで、Xcode起動時に"Hello World"がログに出力されるようになります。

このクラスを編集して、

自作メニューを追加するところまで進めていきます。

AppKitのimport

メニューの編集は、AppKitに含まれているNSMenuなどを利用しますので

AppKitをインポートする必要があります。

import Foundation
import AppKit

class MyPlugin: NSObject {

    class func pluginDidLoad(bundle: NSBundle) {
        NSLog("Hello world :)")
    }

}

NSNotificationを設定

NSAppを利用してメニューをカスタマイズしていきますが、

pluginDidLoad(bundle: NSBundle) が呼ばれた時点では、NSAppはまだ空の状態です。

そこで、アプリケーション起動後に処理を実行するために、

NSNotificationで監視しましょう。

NSApplicationDidFinishLaunchingNotification はアプリケーション起動後のキーです。

このキーを使って登録することで、

アプリケーション起動後にsetMenu()が呼ばれるようになります。

import Foundation
import AppKit

class MyPlugin: NSObject {

    class func pluginDidLoad(bundle: NSBundle) {
        NSLog("Hello world :)")
         
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: "setMenu",
            name: NSApplicationDidFinishLaunchingNotification,
            object: nil
        )
    }

    class func setMenu(){
        NSLog("called MyPlugin setMenu() :)")
    }

}

既存メニューへ項目を追加する

ためしに「Edit」メニューに項目を追加してみましょう。

追加部分だけを書くと、以下のようになります。

 
if let mainMenu = NSApp.mainMenu ?? nil {

    // 既存のメニューに項目を追加する

    let editMenu = mainMenu.itemWithTitle("Edit")
    let newItemInEdit = NSMenuItem(title: "Hello World", action: "printHelloWorld", keyEquivalent: "")

    newItemInEdit.target = self
    editMenu?.submenu?.addItem(newItemInEdit)
}

新しいメニューを自作する

自作メニューを追加する方法はこちらです。

 
if let mainMenu = NSApp.mainMenu ?? nil {

    // 新しいメニューを追加する

    let myMenu = NSMenu(title: "MyMenu")
    let myMenuItem1 = NSMenuItem(title: "Hello World1", action: "printHelloWorld", keyEquivalent: "")
    let myMenuItem2 = NSMenuItem(title: "Who am I", action: "printMe", keyEquivalent: "")

    myMenuItem1.target = self
    myMenuItem2.target = self
    myMenu.addItem(myMenuItem1)
    myMenu.addItem(myMenuItem2)

    let newMenuItem = NSMenuItem(title: "MyMenu", action: nil, keyEquivalent: "")
    newMenuItem.submenu = myMenu

    mainMenu.addItem(newMenuItem)
}

完成

全部くっつけたものが、下のコードです。

このクラスが実行されて、

新しいメニューが追加されていることが確認できれば成功です。

ありがとうございました!

import Foundation
import AppKit

class MyPlugin: NSObject {

    class func pluginDidLoad(bundle: NSBundle) {
        NSLog("Hello world :)")
         
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: "setMenu",
            name: NSApplicationDidFinishLaunchingNotification,
            object: nil
        )
    }

    class func setMenu(){
        NSLog("called MyPlugin setMenu() :)")
 
        if let mainMenu = NSApp.mainMenu ?? nil {

            // 既存のメニューに項目を追加する

            let editMenu = mainMenu.itemWithTitle("Edit")
            let newItemInEdit = NSMenuItem(title: "Hello", action: "hello", keyEquivalent: "")

            newItemInEdit.target = self
            editMenu?.submenu?.addItem(newItemInEdit)

            // 新しいメニューを追加する

            let myMenu = NSMenu(title: "MyMenu")
            let myMenuItem1 = NSMenuItem(title: "Good Morning", action: "goodMorning", keyEquivalent: "")
            let myMenuItem2 = NSMenuItem(title: "Good Afternoon", action: "goodAfternoon", keyEquivalent: "")

            myMenuItem1.target = self
            myMenuItem2.target = self
            myMenu.addItem(myMenuItem1)
            myMenu.addItem(myMenuItem2)

            let newMenuItem = NSMenuItem(title: "MyMenu", action: nil, keyEquivalent: "")
            newMenuItem.submenu = myMenu

            mainMenu.addItem(newMenuItem)
        }
    }

    class func hello(){
        NSLog("Hello:)")
    }
 
    class func goodMorning(){
        NSLog("Good Morning:)")
    }
            
    class func goodAfternoon(){
        NSLog("Good Afternoon:)")
    }
}

元記事 - XcodeのメニューをカスタマイズするプラグインSwiftで作る - Qiita http://qiita.com/i_terasaka/items/86cda2d8af9d85d7785d

参考サイト

初めてのXcode 5 プラグイン開発 - http://dev.classmethod.jp/smartphone/xcode5-plugin-1/

Xcode 5 プラグイン 開発のテクニック - http://dev.classmethod.jp/smartphone/xcode5-plugin-2/

いつかに備えてXcode Plugin作成コトハジメ http://qiita.com/kgmyshin/items/c2e4e270a37882d3306a