Extensions

Extensions are a great way to add new functionality and helpers to Jasonelle. They can be updated separately from the core and be added or removed at will.

Adding an Extension

Extensions are a single *.xcodeproj (blue icon) that contains the project that can be added to the App.xcworkspace (white icon) file.

Step 1

Open App.xcworkspace with Xcode and look for the *.xcodeproj file in Finder.

xcodeproj

Step 2

Draw it to the Extensions directory inside Xcode.

extensions.1

extensions.2

Step 3

Add it to the frameworks in App.xcproj file. Be sure that Embed & Sign option is selected.

added frameworks

Step 4

import the extension in AppExtensions.m.

add.extensions

and add it to the extension registry in install method using the class attribute.

Example: [self.extensions add: JLContacts.class];

install.extensions

Done

If everything is ok then the extension was installed successfully, maybe some other configurations would be needed depending on the extension itself.

Removing an Extension

If you don't need an extension you can remove it from the workspace.

Step 1

Remove (or comment) the setup code in AppExtensions.m file described in Adding an Extension: Step 4.

install.extensions

add.extensions

Step 2

Remove the framework from the App.xcproj file.

added frameworks

Step 3

Delete the *.xcodeproj file from the Workspace. It will pop up a confirmation dialog. We recommend Remove Reference option.

remove reference

Create Extensions

Creating extensions requires some knowledge of Objective-C and JavaScript. These instructions are for advanced users.

Step 1

Create a new xcodeproj file.

new

Select Framework as the template. Be sure that is in the iOS tab.

framework

Add it to the Extensions directory inside the App.xcworkspace.

ext.1

ext.2

Step 2

Configure the iOS Deployment Target to 14.0 (or the recommended version for your project).

d.target

Add the JLKernel framework. Select Do Not Embed as the option. Since all the frameworks will be embeded in App.xcproj later.

d.kernel

Step 3

Create the *.h and *.m files that inherits from JLExtension.

dialog.create.1

dialog.create.2

dialog.create.3

Example

MyExtension.h


#import <Foundation/Foundation.h>

//! Project version number for MyExtension.
FOUNDATION_EXPORT double MyExtensionVersionNumber;

//! Project version string for MyExtension.
FOUNDATION_EXPORT const unsigned char MyExtensionVersionString[];

#import <JLKernel/JLKernel.h>

NS_ASSUME_NONNULL_BEGIN

@interface MyExtension : JLExtension
@end

NS_ASSUME_NONNULL_END

MyExtension.m

#import "MyExtension.h"

@implementation MyExtension

@end

Done

Now you can install it as any other extension in your App.xcodeproj file.

Extension Coding

When coding an extension you can access some events and properties that will enable to add new features to Jasonelle.

- (void) install

This method will be executed when installing the extension in AppDelegate lifecycle. This is before all the extensions are ready, because a single extension is being installed at the time.

Be sure to call the [super install] method.

- (void) install {
    [super install];
    // your code here
}

self.handlers

The handlers are the names of the native bridges that will be called when used inside the webview. Must be configured in the install method.

See JLKeychain extension as an example with using handlers.

- (void) install {
  // ...
  self.handlers = @{
        @"$keychain.set": setHandler,
        @"$keychain.get": getHandler,
        @"$keychain.remove": removeHandler,
        @"$keychain.clear": clearHandler
    };
}
Handlers

A handler is a native function that is called within the webview.

Handlers will be called using $agent.trigger() inside the webview.

  • Example: $agent.trigger('$keychain.get')

They will return a JS Promise.

A wrapper can be created to call directly.

 (() => {
     if (window && window.$myextension) {
         return;
     }
     
     window.$myextension = {};
     window.$myextension.run = () => $agent.trigger("$myextension.run", {});
 })();

- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions

This method is called in AppDelegate after the setup and before loading the webview. Normally for post install logic. All the other extensions would be available at this point.

- (nonnull WKWebView *)appDidLoadWithWebView:(nonnull WKWebView *)webView

This method is called when the WKWebView is ready. You can use it to inject JavaScript files or make additional configurations to the webview element.

- (nonnull WKWebView *)appDidLoadWithWebView:(nonnull WKWebView *)webView {
    [super appDidLoadWithWebView:webView];
    return webView;
}

Examples

See JLCookies as an example extension that only loads a JS file.

More methods

See which other methods are available in JLApplicationExtensions

FileSystem Helper

You can access the filesystem by using the app.utils.fs helper.

Example

Reads a file named JLContacts.js inside the self bundle.

NSString * js = [self.app.utils.fs
                     readJS:@"JLContacts"
                     for:self];

// If is named the same as the class then can be used like this
NSString * js = [self.app.utils.fs
                     readJSFor:self];

WebView Helper

To help injecting scripts to webview you can use app.utils.webview helper.

webView = [self.app.utils.webview inject:@"js.cookie.min" intoWebView:webView for:self];

// Reads the filename as Classname.js
return [self.app.utils.webview inject:self intoWebView:webView];

Extension Service Locator

You can fetch the extension instance by using the app.ext service locator.

return (JLATTrackingManager *) [self.app.ext get:JLATTrackingManager.class];

return (JLApplicationBadge *) [self.app.ext get:JLApplicationBadge.class];