Clone this wiki locally
Structure of a Framework
A framework is a type of CPBundle that provides shared code and resources for Objective-J applications. It is similar to an Application bundle except it doesn't include a main entry point (main.j). The implementation of Frameworks in Cappuccino is similar to Cocoa Frameworks but differs in some ways.
A framework bundle is made of up several types of elements:
- Objective-J code
- Info.plist which describes the bundle
This is the probably the main reason for creating a framework - to share code between applications or create a library that others can use easily with their applications. The source code in a framework is written like any other Objective-J code with a few caveats:
- When using
@importfor a source file within the framework, it is recommended to use the "local" flavor with double-quotes. This indicates to the reader that the import comes from within the framework.
@import "MyClass.j" // best practice @import "MyFramework/MyClass.j" // requires OBJJ_SEARCH_PATHS contains parent directory @import <MyFramework/MyClass.j> // requires OBJJ_SEARCH_PATHS contains parent directory @import <MyClass.j> // doesn't indicate the file is part of the current framework
- All of the sources of the framework must reside in the same directory. The Objj compiler currently cannot compile a framework with sources located in subdirectories, when those sources are imported by other sources in the framework. This will result in a "Duplicate Class" error at compile-time.
The "Resources" directory contains bundle resources. When
CPBundle is used to load and locate resources, it looks in this directory. Since all Objj classes are loaded from bundles (either Application or Framework bundles), the Objj runtime knows what bundle each class comes from, and therefore can look to the "owning bundle" to locate resources. This is the default behavior and can be modified by calling CPBundle's methods directly.
This file is the bundle metadata, it contains key/value pairs of useful things to know about the bundle. There are several predefined keys that have special meaning to CPBundle:
|Info.plist Key||Example Value||Description|
|CPBundleIdentifier||com.mycompany.MyFramework||Unique identifier for the bundle. Intent is to use as a key to store data about the bundle in cookies, databases, local storage etc. Best practice is to use reverse-dns notation to avoid name collisions with other frameworks/applications.|
|CPBundleInfoDictionaryVersion||6.0||Tells CPBundle what keys it can expect in the dictionary. Probably will always be 6.0.|
|CPBundleName||MyFramework||Name of the framework or application|
|CPBundlePackageType||FMWK||Type of bundle, should always be FMWK|
You are free to add your own keys and access them by CPBundle's
objectForInfoDictionaryKey:. This is useful for storing various constant data for the framework rather than hardcode into the sources. For example, it might contain URLs, api keys, etc to access web services the framework is calling.
Creating a Framework
The easiest way to create a framework is to use capp tool
capp gen --template Framework MyFramework
Will create a new skeleton in the folder "MyFramework". Now add any sources and resources you want to include in the framework.
This is the Objj runtime's equivalent of LD_LIBRARY_PATH on *nix systems and Mac OS X's DYLD_FRAMEWORK_PATH. It is a list of directories to look for frameworks in.
By default, OBJJ_SEARCH_PATHS is set to "Frameworks" which refers to the "Frameworks" directory in the application bundle, typically in the same directory as "main.j".
In the browser context, it is a global variable with an array of strings. In the CommonJS context it is a shell environment of colon-separated paths, also accessible through system.env.
For example, to use a common directory for the Cappuccino frameworks, they can be placed in /Frameworks on the web site. Then any application on that site, can access them by setting the following in their index.html file inside
The second path, without the "/" indicates to also search in the application bundle's "Frameworks" directory if a framework can't be found under "/Frameworks".
var ENV = require("system").env; ENV["OBJJ_SEARCH_PATHS"] = "../../Frameworks:Frameworks";
bash$ OBJJ_SEARCH_PATHS="../../Frameworks:Frameworks" jake install
Loading a Resource
Say you have an Info.plist as such:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CPBundleIdentifier</key> <string>net.example.DesignerApp</string> <key>CPBundleName</key> <string>Designer App</string> </dict> </plist>
Inside the following directory structure:
- /Info.plist - /Resources | - /Images | | - icon.png |
Loading a bundle is a simple matter of:
var bundle = [CPBundle bundleWithIdentifier:"net.example.DesignerApp"]; var file = [bundle pathForResource:@"Images/icon.png"]; var image = [[CPImage alloc] initWithContentsOfFile:file];