变更记录
方案名称
Xcode - 插件开发学习备忘
关键字
Xcode \ 插件开发 \ 开发插件
需求场景
- 开发自定义 Xcode 插件
参考链接
- OneV’s Den - Xcode 4 插件制作入门(推荐)
- CocoaChina - Xcode 6 插件开发入门:添加自己的想法和功能
- Forkong - Xcode7 插件开发:从开发到pull到Alcatraz
- ManiacDev - Xcode Plugin Guide – Find Xcode Plugins
- GitHub - Forkong/FKConsole
- GitHub - macoscope/CodePilot(推荐)
- GitHub - zulkis/ZKKeyBindingsTeacher
详细内容
1. 通过插件开发模板创建一个插件
curl -fsSL https://raw.githubusercontent.com/supermarin/Alcatraz/deploy/Scripts/install.sh | sh
(2) 重启 Xcode 选择 Load Bundle,通过 Window -> Package Manager 安装 Xcode Plugin
注:
- 如果无法通过 Alcatraz 安装 Xcode Plugin,可以在 GitHub 上直接下载 Xcode Plugin 编译运行,亦可自动安装插件开发模板
- 安装 Xcode Plugin 前可通过以下命令获取 Xcode UUID ,并在 info.plist -> DVTPlugInCompatibilityUUIDs 中添加该 UUID, 否则无法正常安装
defaults read /Applications/Xcode.app/Contents/Info DVTPlugInCompatibilityUUID
(3) 通过 File -> New -> Project -> Xcode Plugin 创建一个插件模板工程 TestXcodePlugin
2. 为自定义插件添加快捷键支持
(2) 修改 TestXcodePlugin.m 文件如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
| // // TestXcodePlugin.m // TestXcodePlugin // // Created by viktyz on 16/4/3. // Copyright © 2016年 Alfred Jiang. All rights reserved. //
#import "TestXcodePlugin.h" #import "IDEKeyBindingPreferenceSet.h"
#define CP_DEFAULT_SHORTCUT @"$@X" // for key binding system #define DEFAULTS_KEY_BINDING @"TestXcodePlugin.h" #define CP_MENU_PARENT_TITLE @"Edit" #define CP_MENU_ITEM_TITLE @"DoAction"
static NSString * const IDEKeyBindingSetDidActivateNotification = @"IDEKeyBindingSetDidActivateNotification";
@interface TestXcodePlugin()
@property (nonatomic, strong, readwrite) NSBundle *bundle; @property (nonatomic, strong) NSMenuItem *actionMenuItem;
@end
@implementation TestXcodePlugin
+ (instancetype)sharedPlugin { return sharedPlugin; }
- (id)initWithBundle:(NSBundle *)plugin { if (self = [super init]) { // reference to plugin's bundle, for resource access self.bundle = plugin; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didApplicationFinishLaunchingNotification:) name:NSApplicationDidFinishLaunchingNotification object:nil]; } return self; }
- (void)didApplicationFinishLaunchingNotification:(NSNotification*)noti { //removeObserver [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidFinishLaunchingNotification object:nil]; [self setupKeyBindingsIfNeeded]; [self installStandardKeyBinding]; // Create menu items, initialize UI, etc. // Sample Menu Item: NSMenuItem *menuItem = [[NSApp mainMenu] itemWithTitle:CP_MENU_PARENT_TITLE]; if (menuItem) { [[menuItem submenu] addItem:[NSMenuItem separatorItem]]; self.actionMenuItem = [[NSMenuItem alloc] initWithTitle:CP_MENU_ITEM_TITLE action:@selector(doMenuAction) keyEquivalent:@""]; //[actionMenuItem setKeyEquivalentModifierMask:NSAlphaShiftKeyMask | NSControlKeyMask]; [self.actionMenuItem setTarget:self]; [[menuItem submenu] addItem:self.actionMenuItem]; [self updateMenuItem:self.actionMenuItem withShortcut:[self keyboardShortcutFromUserDefaults]]; } [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBindingsHaveChanged:) name:IDEKeyBindingSetDidActivateNotification object:nil]; }
// Sample Action, for menu item: - (void)doMenuAction { NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:@"Hello, World"]; [alert runModal]; }
- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
#pragma mark -
- (id<IDEKeyboardShortcut>)keyboardShortcutFromUserDefaults { Class<IDEKeyboardShortcut> _IDEKeyboardShortcut = NSClassFromString(@"IDEKeyboardShortcut"); return [_IDEKeyboardShortcut keyboardShortcutFromStringRepresentation:[self keyBindingFromUserDefaults]]; }
- (void)setupKeyBindingsIfNeeded { if (IsEmpty([self keyBindingFromUserDefaults])) { [self saveKeyBindingToUserDefaults:CP_DEFAULT_SHORTCUT forKey:DEFAULTS_KEY_BINDING]; } }
- (NSString *)keyBindingFromUserDefaults { return [[NSUserDefaults standardUserDefaults] valueForKey:DEFAULTS_KEY_BINDING]; }
- (void)saveKeyBindingToUserDefaults:(NSString *)keyBinding forKey:(NSString *)defaultsKey { [[NSUserDefaults standardUserDefaults] setObject:keyBinding forKey:defaultsKey]; [[NSUserDefaults standardUserDefaults] synchronize]; }
- (void)keyBindingsHaveChanged:(NSNotification *)notification { [self updateKeyBinding:[self currentUserCPKeyBinding] forMenuItem:self.actionMenuItem defaultsKey:DEFAULTS_KEY_BINDING]; }
- (void)updateKeyBinding:(id<IDEKeyBinding>)keyBinding forMenuItem:(NSMenuItem *)menuItem defaultsKey:(NSString *)defaultsKey { if ([[keyBinding keyboardShortcuts] count] > 0) { id<IDEKeyboardShortcut> keyboardShortcut = [[keyBinding keyboardShortcuts] objectAtIndex:0]; [self saveKeyBindingToUserDefaults:[keyboardShortcut stringRepresentation] forKey:defaultsKey]; [self updateMenuItem:menuItem withShortcut:keyboardShortcut]; } }
- (void)updateMenuItem:(NSMenuItem *)menuItem withShortcut:(id<IDEKeyboardShortcut>)keyboardShortcut { [menuItem setKeyEquivalent:[keyboardShortcut keyEquivalent]]; [menuItem setKeyEquivalentModifierMask:[keyboardShortcut modifierMask]]; }
- (id<IDEKeyBinding>)currentUserCPKeyBinding { return [self menuKeyBindingWithItemTitle:CP_MENU_ITEM_TITLE underMenuCalled:CP_MENU_ITEM_TITLE]; }
- (id<IDEMenuKeyBinding>)menuKeyBindingWithItemTitle:(NSString *)itemTitle underMenuCalled:(NSString *)menuName { Class<IDEKeyBindingPreferenceSet> _IDEKeyBindingPreferenceSet = NSClassFromString(@"IDEKeyBindingPreferenceSet"); id<IDEKeyBindingPreferenceSet> currentPreferenceSet = [[_IDEKeyBindingPreferenceSet preferenceSetsManager] currentPreferenceSet]; id<IDEMenuKeyBindingSet> menuKeyBindingSet = [currentPreferenceSet menuKeyBindingSet] ; for (id<IDEMenuKeyBinding> keyBinding in [menuKeyBindingSet keyBindings]) { if ([[keyBinding group] isEqualToString:menuName] && [[keyBinding title] isEqualToString:itemTitle]) { return keyBinding; } } return nil; }
- (void)installStandardKeyBinding { Class<IDEKeyBindingPreferenceSet> _IDEKeyBindingPreferenceSet = NSClassFromString(@"IDEKeyBindingPreferenceSet"); id<IDEKeyBindingPreferenceSet> currentPreferenceSet = [[_IDEKeyBindingPreferenceSet preferenceSetsManager] currentPreferenceSet]; id<IDEMenuKeyBindingSet> menuKeyBindingSet = [currentPreferenceSet menuKeyBindingSet]; Class<IDEKeyboardShortcut> _IDEKeyboardShortcut = NSClassFromString(@"IDEKeyboardShortcut"); id<IDEKeyboardShortcut> defaultShortcut = [_IDEKeyboardShortcut keyboardShortcutFromStringRepresentation:[self keyBindingFromUserDefaults]]; Class<IDEMenuKeyBinding> _IDEMenuKeyBinding = NSClassFromString(@"IDEMenuKeyBinding"); id<IDEMenuKeyBinding> cpKeyBinding = [_IDEMenuKeyBinding keyBindingWithTitle:CP_MENU_ITEM_TITLE parentTitle:CP_MENU_PARENT_TITLE group:CP_MENU_ITEM_TITLE actions:[NSArray arrayWithObject:@"whatever:"] keyboardShortcuts:[NSArray arrayWithObject:defaultShortcut]]; [cpKeyBinding setCommandIdentifier:CP_MENU_ITEM_TITLE]; [menuKeyBindingSet insertObject:cpKeyBinding inKeyBindingsAtIndex:0]; [menuKeyBindingSet updateDictionary]; }
#pragma mark -
static inline BOOL IsEmpty(id thing) { return thing == nil || ([NSNull null]==thing) || ([thing respondsToSelector:@selector(length)] && [(NSData *)thing length] == 0) || ([thing respondsToSelector:@selector(count)] && [(NSArray *)thing count] == 0); }
@end
|
(3) 修改后,原插件操作按钮旁边会显示快捷键,使用快捷键可触发插件相应事件
效果图
(无)
备注
(无)