bundle在ios和ox中是一个基本的技术,用来封装代码和资源文件的。
bundle使用目录和文件来管理,不管是在开发环境还是先上部署修改都非常容易。
Cocoa和Core Foundation都提供了对bundle内容编程的接口。
一个bundle是一个目录,以标准化的分层结构,它包含可执行代码和资源使用的代码。
不是所有的bundle都是以包的形式存在的。
如何知道是一个包文件,一般可以通过看包文件的扩展名来得到,比如.app, .bundle, .framework, .plugin, .kext
bundle的优势:
1:因为bundle在文件系统中是以目录的形式存在的,所以可以用基本的文件读取接口读取bundle
2:因为bundle的目录结构所致,所以可以很容易就支持国际化
3:bundle可以存在不同的文件系统中
4:用户可以容易的安装,移动,删除bundle
5:大部分bundle还是包,所以不容易受到外部用户对关键资源的操作
6:bundle支持intel系列的芯片,以及32位和64位的机器
7:大多数可执行的代码都是使用bundle的,Applications, frameworks (shared libraries), and plug-ins都支持bundle模型,但是动态库,静态库,脚本,命令行等不支持bundle结构
bundle的几种类型:
Application
Frameworks
Plug-Ins:OS X支持,方便应用动态加载不同的模块,有很多种plug-ins
创建bundle:一般当你创建一个xcode工程的时候,在你编译的时候,会自动生成bundle的
如果是objective-c语言开发的应用,可以使用NSBundle类来获取和管理bundle,如果是c开发的应用,可以使用关联CFBundleRef类型的方法来获取和管理bundle。
使用NSBundle来加载java代码,使用CFBundleRef or CFPlugInRef类型来加载Code Fragment Manager (CFM)代码和c、c++代码。
Application bundle包含文件:info.plist(应用的配置文件)、可执行文件、资源文件、支持文件
Info.plist文件属性:
CFBundleDisplayName:应用的显示名称,在icon下面的
CFBundleIdentifier:com.company.application(一般这样)
LSRequiresIPhoneOS:指定app能在那个ios版本上使用
CFBundleVersion:应用版本号
NSMainNibFile:指定应用的主nib文件
UIStatusBarStyle:
UIStatusBarHidden:
UIInterface-Orientation:
UIRequiresPersistent-WiFi:设置为true,app只能在wifi场景下使用
Framework Bundles:
Mac OS X 扩展了 framework 的功能,让我们能够利用它来共享代码和资源。framework 在概念上有点像 Window 下的库,但是比库更加强大,通过 framework 我们可以共享所有形式的资源,如动态共享库,nib 文件,图像字符资源以及文档等。系统会在需要的时候将 framework 载入内存中,多个应用程序可以同时使用同一个 framework,而内存中的拷贝只有一份。一个 framework 同时也是一个 bundle,我们可以在 finder 里浏览其内容,也可以在代码中通过 NSBundle 访问它。
与动态/静态库相比,framework 有如下优势:
第一,framework 能将不同类型的资源打包在一起,使之易于安装,卸载与定位;
第二,framework 能够进行版本管理,这使得 framework 能不断更新并向后兼容;
第三,在同一时间,即使有多个应用程序使用同一 framework,但在内存中只有一份 framework 只读资源的拷贝,这减少了对内存的占用
如何创建一个framework bundle,可以查看Framework Programming Guide
可加载的bundle不能在IOS中使用,可加载的bundle的目录结构和应用bundle的目录结构差不多
指定国际化的格式:language _region .lproj
English speaking:for Great Britain (en_GB.lproj),Australia (en_AU.lproj), and the United States (en_US.lproj)
访问bundle内容:
如果是Cocoa框架的应用,定位和打开bundle
//objective-c语言获取bundle NSBundle* mainBundle; // Get the main bundle for the app. mainBundle = [NSBundle mainBundle]; //c、c++语言获取bundle CFBundleRef mainBundle; // Get the main bundle for the app mainBundle = CFBundleGetMainBundle();
取回的bundle为空有几种情况:
1:应用没有被打包
2:程序启动的时候,可执行文件路径不对,这个路径可以通过PATH或者启动参数指定
通过指定PATH获取:
NSBundle* myBundle; myBundle = [NSBundle bundleWithPath:@"/Library/MyBundle.bundle"];
如果使用Core Foundation开发的应用:
CFURLRef bundleURL; CFBundleRef myBundle; // Make a CFURLRef from the CFString representation of the // bundle’s path. bundleURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, CFSTR("/Library/MyBundle.bundle"), kCFURLPOSIXPathStyle, true ); // Make a bundle instance using the URLRef. myBundle = CFBundleCreate( kCFAllocatorDefault, bundleURL ); // You can release the URL now. CFRelease( bundleURL ); // Use the bundle... // Release the bundle when done. CFRelease( myBundle );
取回plug-ins在应用中的目录
CFBundleRef mainBundle = CFBundleGetMainBundle(); CFURLRef plugInsURL; CFArrayRef bundleArray; // Get the URL to the application’s PlugIns directory. plugInsURL = CFBundleCopyBuiltInPlugInsURL(mainBundle); // Get the bundle objects for the application’s plug-ins. bundleArray = CFBundleCreateBundlesFromDirectory( kCFAllocatorDefault, plugInsURL, NULL ); // Release the CF objects when done with them. CFRelease( plugInsURL ); CFRelease( bundleArray );
通过bundle id获取bundle:
//cocoa NSBundle* myBundle = [NSBundle bundleWithIdentifier:@"com.apple.myPlugin"]; //core funduction CFBundleRef requestedBundle; // Look for a bundle using its identifier requestedBundle = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.Finder.MyGetInfoPlugIn") );
只要你使用一个的NSBundle对象或CFBundleRef类型来定位资源,你不用担心资源是如何寻找的,它会按照一个优先级来。
没有bundle对象,也可以自己获取bundle里面的内容,通过NSFileManager类来操作,不过如果要获取多个资源文件,建议使用bundle对象。
获取单个文件
//cocoa工程 NSBundle* myBundle = [NSBundle mainBundle]; NSString* myImage = [myBundle pathForResource:@"Seagull" ofType:@"jpg"]; //core funduction工程 CFURLRef seagullURL; // Look for a resource in the main bundle by name and type. seagullURL = CFBundleCopyResourceURL( mainBundle, CFSTR("Seagull"), CFSTR("jpg"), NULL );
获取多个文件(cocoa工程)
//cocoa工程 NSBundle* myBundle = [NSBundle mainBundle]; NSArray* myImages = [myBundle pathsForResourcesOfType:@"jpg" inDirectory:nil]; //core funduction工程 CFArrayRef birdURLs; // Find all of the JPEG images in a given directory. birdURLs = CFBundleCopyResourceURLsOfType( mainBundle, CFSTR("jpg"), CFSTR("BirdImages") );
获取bundle的plist文件中的内容
CFDictionaryRef bundleInfoDict; CFStringRef myPropertyString; // Get an instance of the non-localized keys. bundleInfoDict = CFBundleGetInfoDictionary( myBundle ); // If we succeeded, look for our property. if ( bundleInfoDict != NULL ) { myPropertyString = CFDictionaryGetValue( bundleInfoDict, CFSTR("MyPropertyKey") ); }
获取bundle的版本(using Core Foundation)
// This is the ‘vers’ resource style value for 1.0.0 #define kMyBundleVersion1 0x01008000 UInt32 bundleVersion; // Look for the bundle’s version number. bundleVersion = CFBundleGetVersionNumber( mainBundle ); // Check the bundle version for compatibility with the app. if (bundleVersion < kMyBundleVersion1) return (kErrorFatalBundleTooOld);
使用bundle加载object-c class
- (void)loadBundle:(NSString*)bundlePath { Class exampleClass; id newInstance; NSBundle *bundleToLoad = [NSBundle bundleWithPath:bundlePath]; if (exampleClass = [bundleToLoad principalClass]) { newInstance = [[exampleClass alloc] init]; // [newInstance doSomething]; } }
使用包来管理文件
当文件格式过于复杂,目录结构很多时候,或者有很多不同格式的文件,那么使用包来封装你的整个文件,使用NSFileWrapper来创建文件包,然后通过NSDocument类去读取你的资源文件。如果你使用的是bundle structure,那么你可以通过NSBundle or CFBundleRef类获取文件
打包步骤:
1:定义文档结构
2:注册文档类型
3:创建包