<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [Cocoa]深入淺出Cocoa之Plugin

      深入淺出Cocoa之Plugin

      羅朝輝 (http://www.rzrgm.cn/kesalin/)

      本文遵循“署名-非商業(yè)用途-保持一致”創(chuàng)作公用協(xié)議

      在前文深入淺出Cocoa之Framework中講解了 Framework,接下來講解 plugin。如果你對 Framework 還不太熟悉的話,請閱讀那篇文中,在本例中使用到了 framework,并在本文中沒有詳細講述其創(chuàng)建和使用過程。

      本文代碼下載:點擊這里

      為什么要引入插件?

      我們知道編譯程序時,會連接相關(guān) framework,通常我們所連接的框架是 Foundation 和 Application 框架。當(dāng)程序啟動運行時,每個被連接到的 framework 都會被加載到該程序的 objc 運行時環(huán)境中。如果我們想向正在運行的程序加載新的 framework,那該怎么辦呢?答案之一就是使用 plugin 機制。cocoa 的 plugin 機制通常由 NSBundle 類來實現(xiàn),而實現(xiàn)動態(tài)加載的功能由函數(shù) objc_addClass 來完成。一般我們無需與 objc_addClass 這個函數(shù)打交道,我們使用 NSBundle 來完成絕大部分與 plugin 相關(guān)的工作。


      plugin 機制能夠讓我們開發(fā)出高度模塊化,可定制以及可擴展的應(yīng)用程序,并能夠讓第三方為該應(yīng)用程序添加新特性。想必很多人都熟悉 Eclipse,Eclipse 的 plugin 機制就非常方便與強大。

      NSBundle 簡介

      束(bundle)是文件系統(tǒng)中的一個目錄結(jié)構(gòu),它將程序會使用到的資源打包在一起。這些資源可包括編譯好的代碼,nib文件,配置文件,圖像,聲音,本地化資源等等。束是 Mac OS X 的一個核心特性,應(yīng)用程序,F(xiàn)ramework,插件都是一個束,只是擴展名各異,如應(yīng)用程序的擴展名為 .app;Framework 的擴展名是 .framework;插件的擴展名默認為 .bundle。

      一個 plugin 就是一個 bundle(束),xcode 默認以 .bundle 為擴展名。通常我們使用我們自己定義的擴展名,以便與系統(tǒng)或其他人編寫的 plugin 區(qū)分開來。我們通過 NSBundle 來載入 bundle,并把其中經(jīng)過編譯的類注冊到 objc 運行時中,然后我們就能在程序中使用這些類了;我們也可以使用 bundle 中的所有資源。

      plugin 構(gòu)架

      我們可以通過多種途徑來實現(xiàn)一個 plugin:

      1,定義一個 objc protocol,讓 plugin 遵守該 protocol;
      2,定義一個基類,讓 plugin 繼承該基類;
      3,定義一個 C 回調(diào)函數(shù)接口,讓 plugin 實現(xiàn)改回調(diào)函數(shù);
      4,使用 CFPlugIn 來創(chuàng)建 plugin 接口;


      在今天的例子中,使用的是第二種情況,這種情況稍稍復(fù)雜一些,我們需創(chuàng)建一個 framework 供宿主程序(使用插件的程序)和 plugin 使用,該 framework 的主要職責(zé)是提供基類接口。

      plugin 的存放目錄
      通常 plugin 總是存放在以下三個位置:

      1,應(yīng)用程序名.app/Contents/Plug-ins                               這是程序的開發(fā)者存放隨產(chǎn)品發(fā)布的插件的地方。 
      2,~/Library/Application Support/應(yīng)用程序名/Plug-ins       用戶存放個人插件的地方。
      3,/Library/Application Support/應(yīng)用程序名/Plug-ins         系統(tǒng)中供全部用戶使用的插件。


      在今天的例子中,使用的是第一種情況,即將插件存放在應(yīng)用程序包中。

      創(chuàng)建宿主程序
      我們來創(chuàng)建一個名為 PluginDemo 的 cocoa application,該程序含有一個顯示已安裝 plugin 的 popup button 以及一個執(zhí)行選中 plugin 的 button。


      創(chuàng)建 framework

      1,創(chuàng)建名為 PluginFramework 的 framework,向其中添加 plugin 基類:AbstractPlugin。如果你忘記怎樣創(chuàng)建和使用 framework,請參看前文:深入淺出Cocoa之Framework。


      AbstractPlugin 類僅僅提供兩個接口:

      #import "PluginOne.h"

      @implementation PluginOne

      @synthesize mainWindow;

      - (id)init
      {
      self = [super init];
      if (self) {
      // Initialization code here.

      [NSBundle loadNibNamed:@"PluginOneMainWindow" owner:self];
      }

      return self;
      }

      - (void)dealloc
      {
      mainWindow = nil;

      [super dealloc];
      }

      - (NSString *)name;
      {
      return @"Plugin One";
      }

      - (IBAction)run:(id)sender;
      {
      [mainWindow center];
      [mainWindow makeKeyAndOrderFront:sender];
      }

      - (IBAction)closeWindow:(id)sender;
      {
      [mainWindow orderOut:sender];
      }

      @end

      name 用來標識 plugin,run 用來供宿主程序運行插件。

       

      2,在 PluginDemo 中連接和使用該 framework 來運行插件。如果你忘記怎樣連接和使用 framework,請參看前文:深入淺出Cocoa之Framework。我們在按鈕響應(yīng)函數(shù)中,運行選中的插件。

      - (IBAction)runPlugin:(id)sender
      {
      AbstractPlugin *plugin = [[pluginsController selectedObjects] lastObject];
      if (!plugin)
      return;

      [plugin run:sender];
      }

       

      創(chuàng)建 plugin

      1,創(chuàng)建 plugin;


      2,連接 PluginFramework;如果你忘記怎樣連接和使用 framework,請參看前文:深入淺出Cocoa之Framework


      3,創(chuàng)建 UI 界面;


      4,創(chuàng)建繼承自基類的 plugin 子類:PluginOne;

       

      PluginOne 類繼承自 AbstractPlugin,它僅僅是顯示和隱藏一個 window,其實現(xiàn)如下:

      #import "PluginOne.h"

      @implementation PluginOne

      @synthesize mainWindow;

      - (id)init
      {
      self = [super init];
      if (self) {
      // Initialization code here.

      [NSBundle loadNibNamed:@"PluginOneMainWindow" owner:self];
      }

      return self;
      }

      - (void)dealloc
      {
      mainWindow = nil;

      [super dealloc];
      }

      - (NSString *)name;
      {
      return @"Plugin One";
      }

      - (IBAction)run:(id)sender;
      {
      [mainWindow center];
      [mainWindow makeKeyAndOrderFront:sender];
      }

      - (IBAction)closeWindow:(id)sender;
      {
      [mainWindow orderOut:sender];
      }

      @end

       

      5,plugin 設(shè)置

      下面我們來對 plugin 進行設(shè)置,我們可以設(shè)置其 Principal class,Wrapper Extension(擴展名)。

       

      使用 plugin

      1,宿主程序設(shè)置

      前面說了,在這個例子中,我們打算將插件隨宿主程序一起發(fā)布,所以其存放位置就在宿主應(yīng)用程序包中。因此我們需要在宿主程序種添加一個 Add Copy Files 的 build phase,如下所示:


      2,載入plugin

      在正式的應(yīng)用中,我們應(yīng)該在前面提到的三個目錄下去查找所有 plugin,因為這三個目錄都是 Cocoa 所推薦的 plugin 目錄。在這個例子中,演示的是隨宿主應(yīng)用程序一起發(fā)布的程序,所以我只掃描了應(yīng)用程序包中的目錄。

      - (NSArray *)loadPlugins
      {
      NSBundle *main = [NSBundle mainBundle];
      NSArray *allPlugins = [main pathsForResourcesOfType:@"bundle" inDirectory:@"../PlugIns"];

      NSMutableArray *availablePlugins = [[[NSMutableArray alloc] init] autorelease];

      id plugin = nil;
      NSBundle *pluginBundle = nil;

      for (NSString *path in allPlugins) {
      pluginBundle = [NSBundle bundleWithPath:path];
      [pluginBundle load];

      Class principalClass = [pluginBundle principalClass];
      if (![principalClass isSubclassOfClass:[AbstractPlugin class]]) {
      continue;
      }

      plugin = [[principalClass alloc] init];

      if ([plugin respondsToSelector:@selector(run:)])
      {
      [availablePlugins addObject:plugin];
      NSLog(@" >> loading plugin %@ from %@", [plugin name], path);
      }

      [plugin release];
      plugin = nil;
      pluginBundle = nil;
      }

      return availablePlugins;
      }


      該函數(shù)在 init 中被調(diào)用:

      - (id)init
      {
      self = [super init];
      if (self) {
      plugins = [[self loadPlugins] retain];
      }

      return self;
      }

       

      下面提供一個函數(shù)掃描前面提到的三個目錄,你可以用這個函數(shù)提到上面代碼中對 loadPlugins 的調(diào)用:

      - (NSArray *)loadAllPlugins
      {
      NSString *appName = @"PluginOne/Plugins";
      NSString *appSupport = @"Library/Application Support";
      appSupport = [appSupport stringByAppendingPathComponent:appName];

      NSString *appPath = [[NSBundle mainBundle] builtInPlugInsPath];
      NSString *userPath = [NSHomeDirectory() stringByAppendingPathComponent:appSupport];
      NSString *sysPath = [@"/" stringByAppendingPathComponent:appSupport];

      NSArray* paths = [NSArray arrayWithObjects:appPath, userPath, sysPath, nil];

      NSMutableArray * availablePlugins = [[[NSMutableArray alloc] init] autorelease];
      for (NSString * path in paths)
      {
      NSLog(@" >> Search in directory: %@", path);

      NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];
      for (NSString *fileName in contents)
      {
      if ( [[fileName pathExtension] isEqualToString:@"plugin"] || [[fileName pathExtension] isEqualToString:@"bundle"])
      {
      NSString *fullPath = [path stringByAppendingPathComponent:fileName];
      NSBundle *pluginBundle = [NSBundle bundleWithPath:fullPath];
      if (pluginBundle && [pluginBundle load])
      {
      Class principalClass = [pluginBundle principalClass];
      if (![principalClass isSubclassOfClass:[AbstractPlugin class]]) {
      continue;
      }

      id plugin = [[principalClass alloc] init];

      if ([plugin respondsToSelector:@selector(run:)])
      {
      [availablePlugins addObject:plugin];
      NSLog(@" >> loading plugin %@ from %@", [plugin name], path);
      }

      [plugin release];
      plugin = nil;
      }
      }
      }
      }

      return availablePlugins;
      }

       

      顯示 plugin 列表的 popupbutton 的內(nèi)容被綁定到該 plugins 數(shù)組,所以程序啟動之后,就能顯示 plugin 的列表。運行結(jié)果如下:

       

      點擊運行之后,就能顯示出插件主界面:

       

      引用資源:
      Code Loading Programming Topics provides information about writing plug-ins using the Objective-C language.
      Bundle Programming Guide provides an overview to bundles, including their purpose, types, structure, and the API for accessing bundle resources.

      posted @ 2011-10-28 13:35  飄飄白云  閱讀(1661)  評論(0)    收藏  舉報
      本博客遵循 Creative Commons License “署名-非商業(yè)用途-保持一致”創(chuàng)作共用協(xié)議。 與我聯(lián)系
      主站蜘蛛池模板: 亚洲午夜无码久久久久蜜臀AV | 97久久精品人人做人人爽| 日韩激情一区二区三区| 潘金莲高清dvd碟片| 中文国产不卡一区二区| 99国产精品一区二区蜜臀| 97午夜理论电影影院| 精品婷婷色一区二区三区| 国产极品精品自在线不卡| 亚洲最大的成人网站| 国产精品久久久久婷婷五月| 虎林市| 亚洲免费一区二区av| 免费无码黄网站在线观看| 无套中出极品少妇白浆| 亚洲精品乱码久久久久久中文字幕| 国产精品免费第一区二区| 男人下部进女人下部视频| 精品精品久久宅男的天堂| 久久不见久久见www日本| 九九成人免费视频| 亚洲精品中文字幕一区二| 亚洲精品欧美综合二区| 亚洲精品天堂在线观看| 日韩精品中文字幕一线不卡| 人妻少妇精品无码专区二区| 婷婷丁香五月亚洲中文字幕| 亚洲永久精品日本久精品| 国产精品久久久久aaaa| 少妇又爽又刺激视频| 精品黄色av一区二区三区| 国产美女被遭强高潮免费一视频| 全部免费毛片在线播放| 成在线人免费视频| 久久精品国产一区二区三| 亚洲高清WWW色好看美女| 欧美一区二区三区成人久久片| 女同性恋一区二区三区视频| 国产又色又爽又黄的视频在线 | 亚洲一区二区三区蜜桃臀| 国厂精品114福利电影免费|