iOS Tutorial Add QuickActions to your App

Hi,

in this thread I want to show you, how to add QuickActions/Shortcuts to your App. QuickActions require 3D touch support and iOS 9 (minimum).

1.) Download the QuickActions tool, to create a #PlistExtra string (note: you are not allowed, to have more than 4 actions)
2.) Paste the #PlistExtra string to the project attributes region
3.) Download the QuickActions module and add it to your project
4.) Add the following code:

B4X:
Private Sub Application_Start (Nav As NavigationController)
    QuickActions.StartSettings
    ...
    ...
    ...
End Sub

Private Sub Application_Active
    QuickActions.ActiveSettings
End Sub

Private Sub Application_Inactive
    QuickActions.InactiveSettings
End Sub
Use the Objective-C code by Erel in post #3 instead.

5.) To know wheter a shortcut item was clicked, use the ShortcutItemClicked event:
B4X:
Sub Application_ShortcutItemClicked (ItemType As String)
    Log($"QuickAction: ${ItemType}"$)
End Sub


If you are using a CustomIcon, put the icon file in to the Special folder.

If you don't have a iDevice, which supports 3D touch, but a local/virtual mac you can use this tool: https://github.com/PoomSmart/SBShortcutMenuSimulator for tests.

Feel free to ask questions ;)

Jan
 

Attachments

  • Tool.zip
    321.2 KB · Views: 341
  • QuickActions.bas
    2.2 KB · Views: 400
  • Example.zip
    2 KB · Views: 332
Last edited:

schimanski

Well-Known Member
Licensed User
Thank you for this great class!

I only have one problem: The sub Application_OpenUrl (Url As String, Data As Object, SourceApplication As String) is no longer raised. Do I have to account something else?
 

Erel

Administrator
Staff member
Licensed User
The QuickActions module replaces the default delegate with its own. A better approach will be to add the required method to the default delegate.

Add this code to the main module and remove QuickActions module.
B4X:
#if OBJC
@end
@implementation B4IAppDelegate (shortcut)
-(void)application:(UIApplication *)application
performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem
completionHandler:(void (^)(BOOL succeeded))completionHandler{
B4I* bi = [b4i_main new].bi;
[bi raiseEvent:nil event:@"application_shortcutitemclicked:" params:@[shortcutItem.type]];
completionHandler(YES);
}
#End If

Add this code after the end of the main module.
 
Last edited:

schimanski

Well-Known Member
Licensed User
Thank you very much. With this code, the Application_xxx subs are all raised normaly. But there is now a new problem: I use now 4 OBJC-sections in my main module. With adding your QuickAction code, the other three sections raises now an method not found-exception. For example the exception from the fixorientation-objc-code:

B4X:
Error occurred on line: 2612 (Main)
Method not found: fixOrientation:, target: <b4i_main: (null)>
Stack Trace: (
  CoreFoundation       <redacted> + 148
  libobjc.A.dylib      objc_exception_throw + 56
  CoreFoundation       <redacted> + 0
  EIS                  +[B4I runDynamicMethod:method:throwErrorIfMissing:args:] + 388
  EIS                  -[B4INativeObject RunMethod::] + 216
  EIS                  -[b4i_main _fixorientation_image:] + 1156
  EIS                  -[b4i_main _anhang_bild:] + 696
  EIS                  -[b4i_main _kamera_complete:::] + 2096
  CoreFoundation       <redacted> + 144
  CoreFoundation       <redacted> + 292
 EIS                  +[B4I runDynamicMethod:method:throwErrorIfMissing:args:] + 1624
 EIS                  -[B4IShell runMethod:] + 448
 EIS                  -[B4IShell raiseEventImpl:method:args::] + 1784
 EIS                  -[B4IShellBI raiseEvent:event:params:] + 1408
 EIS                  +[B4IObjectWrapper raiseEvent:::] + 300
 EIS                  -[B4ICameraDelegate imagePickerController:didFinishPickingMediaWithInfo:] + 504
 UIKit                <redacted> + 128
 UIKit                <redacted> + 44
 libdispatch.dylib    <redacted> + 24
 libdispatch.dylib    <redacted> + 16
 libdispatch.dylib    <redacted> + 968
 CoreFoundation       <redacted> + 12
 CoreFoundation       <redacted> + 2012
 CoreFoundation       CFRunLoopRunSpecific + 436
 GraphicsServices     GSEventRunModal + 100
 UIKit                UIApplicationMain + 236
 EIS                  main + 124
 libdyld.dylib        <redacted> + 4
)
 

narek adonts

Well-Known Member
Licensed User
The QuickActions module replaces the default delegate with its own. A better approach will be to add the required method to the default delegate.

Add this code to the main module and remove QuickActions module.
B4X:
#if OBJC
@end
@implementation B4IAppDelegate (shortcut)
-(void)application:(UIApplication *)application
performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem
completionHandler:(void (^)(BOOL succeeded))completionHandler{
B4I* bi = [b4i_main new].bi;
[bi raiseEvent:nil event:@"application_shortcutitemclicked:" params:@[shortcutItem.type]];
completionHandler(YES);
}
#End If

Add this code after at the end of the module.
This is a good snippet for objc part. Is there a way like this to add delegate methods for other controls or object like tableview, textfield,... ?
 

Erel

Administrator
Staff member
Licensed User
This is a great feature to add to your apps. It is very simple (use the OBJC snippet instead of the module) and it adds a nice touch.
Apple are now more strict with their policies and they might reject apps that lack native features with the explanation that it should have been implemented as a web app.
I think that this feature can help in such cases.
 
Top