zoukankan      html  css  js  c++  java
  • HokeyPokey — WWDC讲师特供XCode插件高仿版的设计与实现

       在我们使用XCode IDE做iOS技术分享的时候,经常会涉及到多个方案的运行效果比较。切换不同的演示方案通常有如下三种方法:1.分成多个XCode项目;2.分成多个版本Branch 3.手动去注释掉非本次运行方案的代码块。这三种方案在灵活性和操作速度及方便性上,或多或少有些差强人意。那么,有没有更好的方法呢?看多了WWDC视频的童鞋或许会注意到这个名字:Hokey Pokey, 中文是变戏法的意思,WWDC讲师在切换不同的演示方案时,快捷键唤起一个浮窗,在浮窗中勾选不同的演示代码块。笔者编码实现的正是这样一款WWDC讲师特供XCode插件的高(简易)仿(山寨)版(货)。

      在线维护:https://github.com/1962449521/HokeyPokey

    一、HokeyPokey插件的效果演示

      HokeyPokey菜单项安装在Xcode View -> HokeyPokey中。有[Hide/Show]、[Make]、[Resume]三个功能项,分别用于展示/销毁HokeyPokey工作窗口、将当前操作文件编译至hokey pokey 管理数据库、撤销当前文件的所有hokey pokey操作及数据库。工作窗口右上角放有按钮,用于切换窗口是否永远在最前面。相同运行方案名的分散代码块将被归为一个列表行。对某个方案的选择通过双击列表项来实现。三个功能项的快捷键、工作窗口的表头提供了方案定制,稍后介绍。

     

    二、使用该插件目前版本需注意的地方

      1. 尽量只打开一个XCode窗口、在一个XCode窗口中只打开一个Tab项。这里存在的问题是在切换XCode窗口或Tab项时,HokeyPokey窗口没有同步更新,双击其中列表项时,会将最初文件操作结果写入到新的代码编辑区。

      2. 撤销HokeyPokey操作需逐个文件进行(第三个功能项Resume)。当只打开一个Xcode窗口一个Tab项时,HokeyPokey窗口会根据文件的切换自动更新。操作粒度为一个文件而不是一个工程,因此当需要撤销所有HokeyPokey操作时需逐个切换到操作过的文件,逐个撤销。

      3. 编辑文件时,需先撤销该文件的HokeyPokey更改(部分代码被隐藏),然后修改后,再编译至HokeyPokey数据库(第二个功能项Make)。

      4. 右上角的dock/normal可以切换HokeyPokey窗口是否永远保持最前面

    三、关于插件的安装和自定义设置

      该插件运行即安装,从github下载插件工程到本地,使用默认设置或更改设置文件后,运行XCode项目即可。自定义设置涉及的文件为HPKConst.h,具体如下图。可以更识别标志、案、快捷键等。该插件作为开源欢迎及希望童鞋们更改、使用、传播和多提意见。但本着尊重出发请不要修改插件名、作者声明等,

    #ifndef HPKConst_h
    #define HPKConst_h
    
    // ------------ hokeypokey识别的开始和结束标志
    #define HPKStartStringTag             @"//hokey"
    #define HPKEndStringTag               @"//pokey"
    
    // ------------ 表头和窗口状态切换的UI文案
    #define HPKHeaderTitle4Show           @"SHOW"
    #define HPKHeaderTitle4Identifier     @"IDENTIFIER"
    
    #define HPKLabel4WindowDock           @"dock"
    #define HPKLable4WindowNormal         @"normal"
    
    // ------------ 快捷键设置
    #define HPKRequireKey4HideShow        @YES
    #define HPKKeyEquivalent4HideShow     @"h"
    #define HPKKeyMask4HideShow           NSShiftKeyMask | NSCommandKeyMask
    
    #define HPKRequireKey4Make            @YES
    #define HPKKeyEquivalent4Make         @"w"
    #define HPKKeyMask4Make               NSShiftKeyMask | NSCommandKeyMask
    
    #define HPKRequireKey4Resume          @YES
    #define HPKKeyEquivalent4Resume       @"x"
    #define HPKKeyMask4Resume             NSShiftKeyMask | NSCommandKeyMask
    
    // ------------ 以下请勿更改
    #define HPKIsShownKey                 @"isShow"
    #define HPKTitleKey                   @"identifier"
    #define HPKPockyResultsKey            @"pockyResultsKey"
    #define HPKFileURLKey                 @"fileURLKey"
    
    #endif /* HPKConst_h */

    四、插件的需求和功能分析

      1. 使用场景和需求分析

      在技术分享或授课时,用于Xcode项目的运行方案区分与切换。需要与文章开始时提到的三种方法作比较,达到更加易用,省时的目的。

      2. 功能分析

      首先要求用户给出格式化的textView并触发hokeypokey编译。用户使用格式化的标志,即用识别开始标志(如//hokey) 和识别结束标志(//pokey)将一个TextView内容分隔成若干块。开始标识和结束标识之间用于存放不同方案的特有代码块,其它隔断为共用的代码块。

      在这个格式前提下,插件开发的最基本功能,可以细化至以下几项:

      a. 提取出方案特有代码块。给定格式字符串,提取出方案特有代码块的字符串、所在初始字符串中的Range,以及各代码块的方案名(标识) ;

      b. 运算得出对应方案的可运行代码。给定格式字符串和hokeypokey提取结果,给定不同的方案名选择时,能运算得出对应方案的可运行代码;

      c. 当前方案选择可视化。给出GUI显示,将提取结果绘制至列表控件,并在UI上给出提示各块显示与否的提示;

      d. 提供方案切换方法。GUI允许用户交互,在列表项双击时,能够切换方案选择状态、XCode代码编辑区显示和物理文档。

     

    五、插件的设计与实现

      功能点a、b的实现通过给NSString添加Category方法,类设计如下,对应功能a、b分别提供了两个实例方法,并设计了HPKSearchResult模型用于存放分块结果。

    @interface HPKSearchResult : NSObject
    
    @property (nonatomic, strong) NSString *title;
    @property (nonatomic, assign) NSRange  range;
    @property (nonatomic, strong) NSString *string;
    
    -(instancetype) initWithRange:(NSRange)aRange string:(NSString *)aString title:(NSString *)aTitle;
    
    @end
    
    
    @interface NSString (HPKTextGetter)
    
    - (NSArray<HPKSearchResult *> *) HPK_textResultsWithPairOpenString:(NSString *)open
                                                           closeString:(NSString *)close;
    
    - (NSString *) HPK_stringBySubtractSearchResults:(NSArray<HPKSearchResult *> *) searchResults;
    
    @end

      功能c、d主要通过一个自定义窗口以及Cocoa Binding来实现,类设计如下。窗口的标题windowTitle和列表内容cotentArray需要随着当前操作文件的变化而变化。数据源由管理类HPKPluginMain提供,这里简单起见,直接将tableView、windowTitle、contentArray等属性暴露出来,由管理类HPKPluginMain直接操作。该窗口类绑定了用户对列表的双击动作,从而更新HokeyPokey窗口列表及将操作提交到管理类HPKPluginMain作实质操作。

    #import <Cocoa/Cocoa.h>
    
    @class HPKPluginMain;
    @interface HPKWindowController : NSWindowController
    
    @property (weak) HPKPluginMain *pluginMain;// 插件管理对象
    @property (weak) IBOutlet NSTableView *tableView;// 插件窗口主控件
    
    // 文案内容绑定
    @property (strong)  NSString *windowTitle;
    @property (strong)  IBOutlet NSArrayController *contentArray;
    
    // 用户双击事件绑定
    - (void) inspect:(NSArray *)selectedObjects;
    
    @end
    
    @interface HPKWindowController () <NSTableViewDelegate>
    
    // 文案内容绑定
    @property (strong)  NSString *headerTitle4Show;
    @property (strong)  NSString *headerTitle4Identifier;
    
    // 切换窗口显示是否悬浮按钮
    @property (weak) IBOutlet NSButton *btnDock;
    
    @end

       管理类的设计,首先是作为HokeyPokey窗口的数据源为其提供显示数据,第二是作为HokeyPokey窗口的委托,处理交互引起的业务逻辑。数据源方面主要用了两个字典来实现,其key值都是物理文件的url,originalTextDic存放其在编译HokeyPokey时的原始字符串,contentArrDic存放各文件对应的HokeyPokey提取结果。

    #import <Cocoa/Cocoa.h>
    
    @interface HPKPluginMain : NSObject
    
    /**
     *  根据用户对hokey pokey窗口的点击更新XCode显示和物理文档
     *
     *  @param editedTitle 要操作的方案名
     *  @param isShow      该方案是否显示
     */
    - (void) refreshEditorAndFileAtTiltle:(NSString *)editedTitle shouldShow:(BOOL)shouldShow;
    
    @end
    
    
    
    @interface HPKPluginMain() <NSWindowDelegate>
    
    // hokey pokey数据库
    @property (nonatomic, strong) NSMutableDictionary *originalTextDic;
    @property (nonatomic, strong) NSMutableDictionary *contentArrDic;
    
    // 代码编辑窗口
    @property (nonatomic, strong) DVTSourceTextView  *ideSourceTextView;
    @property (nonatomic, strong) IDEWorkspaceWindow *ideWorkspaceWindow;
    
    @property (nonatomic, strong) HPKWindowController *windowController;// 持有hokeypokey窗口
    @property (nonatomic, strong) WHUKVOController    *documentKVO;     // facebook的KVO类
    
    - (void) createHokeyPokeyMenu;  // 创建菜单
    - (void) createHokeyPokeyWindow;// 创建hokeypokey窗口
    - ( NSURL *) activeDocumentURL; // 返回当前编辑文档的地址
    - (void) refreshHokeyPokeyWindowWithURL:(NSURL *)url;// 刷新hokeypokey窗口的数据库源
    
    @end

    六、注意点和未完成的工作

      不要在平时开发中打开HokeyPokey窗口,以免误操作。

      只在技术分享、方案演示时使用,使用前一定要备份,以免忘记撤消,XCode关闭导致代码的丢失。

      使用时只打开一个XCode工程,一个Tab项。

      目前的文件切换是未支持Undo Manager的,可以用粘贴板和虚拟键值来实现。在关闭窗口之前,我们很可能忘记了HokeyPokey窗口有隐藏内容,是否需要在XCode退出时自动撤销所有HokeyPokey操作?同时打开多个XCode工程或Tab时是否需要做同步?这些问题将在以后的版本维护中逐渐解决。

  • 相关阅读:
    1062 Talent and Virtue (25 分)
    1083 List Grades (25 分)
    1149 Dangerous Goods Packaging (25 分)
    1121 Damn Single (25 分)
    1120 Friend Numbers (20 分)
    1084 Broken Keyboard (20 分)
    1092 To Buy or Not to Buy (20 分)
    数组与链表
    二叉树
    时间复杂度与空间复杂度
  • 原文地址:https://www.cnblogs.com/hushuai-ios/p/5402037.html
Copyright © 2011-2022 走看看