Xcode plugins 开发
Xcode plugins 开发
@(iOS)[Xcode]
背景介绍
- 搞这个呢,主要是项目中要用的字段太多了,有时一个界面要一百多个字段(一个字段一个属性对应一个View),每次赋值粘贴都要疯了。前几天写了个python小脚本,使用起来不是很方便,所以冒出这个想法:做一个小插件试试。
原理
- 在Xcode启动的时候,Xcode将会寻找位于
~/Library/Application Support/Developer/Shared/Xcode/Plug-ins
文件夹中的后缀名为.xcplugin
的bundle作为插件进行加载(运行其中的可执行文件),这就可以令我们光明正大合法合理地将我们的代码注入(虽然这个词有点不好听)Xcode,并得到运行。因此,想要创建Xcode插件,我们需要创建Bundle工程并将编译的bundle放到上面所说的插件目录中去,这就是Xcode插件的原理。 - 因为是注入方式添加插件,所以如果插件有问题闪退,那么Xcode也会闪退。
项目配置
Xcode plugins
开发的话,没有任何官方文档,而且在新建项目时要配置很多参数,作为小白的我可是搞了大半天也没配置正确,这里使用大神的template(Xcode plugins
)来创建项目。- 通过
Alcatraz
安装模板
- 新建工程
- 其中几处关键的地方是plist中新增两个BOOL值,通过模板已经设置过
XCPluginHasUI = NO
XC4Compatible = YES
- 然后就是Bulid Setting 里设置的参数
示例代码
//
// SLQPluginDemo.m
// SLQPluginDemo
//
// Created by Christian on 16/7/30.
// Copyright © 2016年 MrSong. All rights reserved.
//
#import "SLQPluginDemo.h"
static SLQPluginDemo *sharedPlugin; // 单例对象
@implementation SLQPluginDemo
#pragma mark - Initialization
+ (void)pluginDidLoad:(NSBundle *)plugin
{
NSArray *allowedLoaders = [plugin objectForInfoDictionaryKey:@"me.delisa.XcodePluginBase.AllowedLoaders"];
if ([allowedLoaders containsObject:[[NSBundle mainBundle] bundleIdentifier]]) {
sharedPlugin = [[self alloc] initWithBundle:plugin];
}
}
+ (instancetype)sharedPlugin
{
return sharedPlugin;
}
- (id)initWithBundle:(NSBundle *)bundle
{
if (self = [super init]) {
// reference to plugin's bundle, for resource access
_bundle = bundle;
// NSApp may be nil if the plugin is loaded from the xcodebuild command line tool
if (NSApp && !NSApp.mainMenu) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidFinishLaunching:)
name:NSApplicationDidFinishLaunchingNotification
object:nil];
} else {
[self initializeAndLog];
}
}
return self;
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidFinishLaunchingNotification object:nil];
[self initializeAndLog];
}
- (void)initializeAndLog
{
NSString *name = [self.bundle objectForInfoDictionaryKey:@"CFBundleName"];
NSString *version = [self.bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
NSString *status = [self initialize] ? @"loaded successfully" : @"failed to load";
NSLog(@"🔌 Plugin %@ %@ %@", name, version, status);
}
#pragma mark - Implementation
- (BOOL)initialize
{
// Create menu items, initialize UI, etc.
// Sample Menu Item:
NSMenuItem *menuItem = [[NSApp mainMenu] itemWithTitle:@"Edit"];
if (menuItem) {
[[menuItem submenu] addItem:[NSMenuItem separatorItem]];
NSMenuItem *actionMenuItem = [[NSMenuItem alloc] initWithTitle:@"Do Action" action:@selector(doMenuAction) keyEquivalent:@""];
//[actionMenuItem setKeyEquivalentModifierMask:NSAlphaShiftKeyMask | NSControlKeyMask];
[actionMenuItem setTarget:self];
[[menuItem submenu] addItem:actionMenuItem];
return YES;
} else {
return NO;
}
}
// 相应点击
- (void)doMenuAction
{
[self loadWindowAndPutInFront];
}
// 弹出窗口
- (void)loadWindowAndPutInFront {
if (!self.windowController.window)
self.windowController = [[TransferViewController alloc] initWithBundle:self.bundle];
[[self.windowController window] makeKeyAndOrderFront:self];
}
@end
- 在点击
doMenuAction
处理自己要处理的事情就行,可以弹出一个窗口之类的。或者只是添加监听。
提交到Alcatraz
- 主要过程就是下载这个仓库 https://github.com/supermarin/alcatraz-packages
- 然后添加自己的项目到
plugins
数组中,格式如下
{
"name": "OCPropertyTransfer",
"url": "https://github.com/slq0378/OCPropertyTransfer",
"description": "Transfer assigned string to property",
"screenshot": "https://github.com/slq0378/OCPropertyTransfer/blob/master/OCPropertyTransfer%E4%BD%BF%E7%94%A8.gif"
},
- 接着就是要测试一下自己添加的格式是否正确,使用ruby测试
sudo gem install rspec
- 到工程目录,执行
rspec
song$ rspec
.......
Finished in 0.07776 seconds (files took 0.33704 seconds to load)
7 examples, 0 failures
-
每一问题,就可以push 到github了
-
其他
- 其中安装
rspec
出了问题,解决方法如下 - 通过brew重新安装ruby
参考
本文来自博客园,作者:struggle_time,转载请注明原文链接:https://www.cnblogs.com/songliquan/p/12784428.html