[Cocoa] a simple introduction to cocoa plug-in

Source: Internet
Author: User

Introduction to cocoa plug-in

Luo chaohui (http://www.cnblogs.com/kesalin)

This article follows the "signature-non-commercial use-consistency" creation public agreement

In the previous article, I explained the framework in the framework of cocoa, and then explained the plug-in. If you are not familiar with the framework, read the article, use the framework in this example, and do not detail the creation and use process in this article.

This articleCodeDownload: click here

Why introduce plug-ins?

We know how to compileProgramThe framework is connected. Generally, the framework we connect is the foundation and application framework. When the program starts to run, each connected framework is loaded into the objc runtime environment of the program. What should we do if we want to load a new framework to a running program? One of the answers is to use the plugin mechanism. The plug-in mechanism of cocoa is usually implemented by the nsbundle class, and the function objc_addclass is used to realize dynamic loading. Generally, we do not need to deal with the objc_addclass function. We use nsbundle to do most of the work related to plugin.

The plugin mechanism allows us to develop highly modular, customizable, and scalable applications, and allows third parties to add new features to the application. Many people are familiar with eclipse, and eclipse's plug-in mechanism is very convenient and powerful.

Introduction to nsbundle

Bundle is a directory structure in the file system. It packs the resources used by the program. These resources can include compiled code, NIB files, configuration files, images, sounds, and localized resources. Bundle is a core feature of Mac OS X. Applications, frameworks, and plug-ins all have different extensions, for example, the application extension is. the extension of APP and framework is. framework; default extension of the plug-in is. bundle.

A plugin is a bundle. By default, xcode uses. Bundle as the extension. We usually use our own defined extension to distinguish it from the system or the plug-in compiled by others. We use nsbundle to load the bundle and register the compiled classes in the objc runtime. Then we can use these classes in the program; we can also use all resources in the bundle.

Plugin Architecture

We can implement a plugin in multiple ways:

1. Define an objc protocol so that the plugin complies with the protocol;
2. Define a base class so that plugin can inherit the base class;
3. Define a C callback function interface for plugin to implement the callback function;
4. Use cfplugin to create the plugin interface;

In today's example, the second situation is used. This situation is slightly more complex. We need to create a framework for the host Program (the program using the plug-in) and plugin, this framework is mainly responsible for providing basic class interfaces.

Directory for storing plugin
Normally, plugin is stored in the following three locations:

1. Application name. APP/contents/plug-ins this is where the developer of the program stores the plug-ins released with the product.
2 ,~ /Library/Application Support/Application name/plug-ins the place where the user stores the personal plug-in.
3. Plug-ins in the/library/Application Support/Application name/plug-ins system for all users.

In today's example, the first case is to store the plug-in the application package.

Create a Host Program
Create a cocoa application named plugindemo. This program contains a popup button that shows the installed plugin and a button that executes the selected plugin.

Create framework

1. Create a framework named pluginframework and add the plugin base class: abstractplugin to it. If you forget how to create and use the framework, refer to the previous article: a simple introduction to the cocoa framework.

The abstractplugin class only provides two interfaces:

# 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 is used to identify plugin, and run is used for the host to run the plug-in.

 

2. connect to and use the Framework to run the plug-in plugindemo. If you forget how to connect to and use the framework, refer to the previous article: a simple introduction to the cocoa framework. In the button response function, run the selected plug-in.

 
-(Ibaction) runplugin :( ID) sender
{
Abstractplugin * plugin = [[pluginscontroller selectedobjects] lastobject];
If(! Plugin)
Return;

[Plugin run: sender];
}

 

Create plugin

1. Create plugin;

2. Connect to pluginframework. If you forget how to connect to and use the framework, refer to the previous article: A Brief Introduction to the cocoa framework.

3. Create a UI;

4. Create a in subclass inherited from the base class: pluginone;

 

The pluginone class inherits from abstractplugin. It only shows and hides a window, and its implementation is as follows:

# 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 settings

Next we will set plugin. We can set its principal class and wrapper extension (Extension ).

 

Use plugin

1. Host Program settings

As mentioned above, in this example, we plan to release the plug-in along with the Host Program, so its storage location is in the Host application package. Therefore, we need to add a build phase of add copy files in the Host Program, as shown below:

2. Load plugin

In the formal application, we should find all the Plugins under the three directories mentioned above, because these three directories are the plugin directories recommended by cocoa. In this example, the program is released along with the Host application, so I only scanned the directory in the application package.

-(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;
}

This function is called in init:

-(ID) Init
{
Self = [Super init];
If(Self ){
Plugins = [[self loadplugins] retain];
}

ReturnSelf;
}

 

The following provides a function to scan the three directories mentioned above. You can use this function to call loadplugins in the code above:

-(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 * pathIn Paths)
{
Nslog ( @" > Search in Directory: % @ " , PATH );

Nsarray * Contents = [[nsfilemanager defaultmanager] contentsofdirectoryatpath: path error: NULL];
For (Nsstring * filename In Contents)
{
If ([[Filename pathextension] isw.tostring: @" Plugin " ] | [[Filename pathextension] isw.tostring: @" Bundle " ])
{
Nsstring * fullpath = [path stringbyappendingpathcomponent: Filename];
Nsbundle * pluginbundle = [nsbundle bundlewithpath: fullpath];
If (Pluginbundle & [pluginbundle load])
{
Class principalclass = [pluginbundle principalclass];
If (! [Principalclass issubclassofclass: [abstractpluginClass ]) {
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;
}

 

The popupbutton content that shows the plugin list is bound to the Plugins array. After the program is started, the plugin list is displayed. The running result is as follows:

 

Click Run to display the main interface of the plug-in:

 

Reference resources:
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.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.