Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198

Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198

Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198
WorkflowKit.framework - iPhone Development Wiki

WorkflowKit.framework

From iPhone Development Wiki
Revision as of 02:08, 10 April 2022 by Zachary7829 (talk | contribs) (change isEqual to isEqualToString)
WorkflowKit.framework
Private Framework
Availabile 12.0 – present
Headers [headers.cynder.me]


WorkflowKit is the framework that acts as a backend to the Shortcuts app. It provides around 80% functionality of the Shortcuts app including (but not limited to) actions (though ActionKit also powers a lot of them), handles how shortcuts are imported, how they're stored, etc. It is noted that while it is technically added in 12.0, most of its functionality came in iOS 13.0.

For examples on how to use this framework, see the Example Code section of this page.

WFWorkflowRecord

WFWorkflowRecord is how shortcuts are stored. The biggest thing is actions: Every action has an action identifier to identify an action (WFWorkflowActionIdentifier), and some have parameters of what is in said action (WFWorkflowActionParameters). However, it also handles other data about the shortcut, such as its name and minimum client version it can be imported on.

WFBundledActionProvider

WFBundledActionProvider is what provides WorkflowKit with what actions it loads.

WFAction

WFAction is basically the class that every shortcuts action uses. It should be noted that actions aren't all WFAction, but rather their own class that inherit from it (For example, WFExitShortcut in ActionKit).

Example Code

Replacing Return to Homescreen with Exit Shortcut upon shortcut import

%hook WFSharedShortcut
-(id)workflowRecord {
// WFWorkflowRecord handles how shortcuts are stored and hooking it will affect every shortcut loaded - not only is this bad for performance, but if you make a mistake, every shortcut will be affected, hence it's best to avoid hooking it when possible. Here, we hook WFSharedShortcut and affect its workflow record instead
    id rettype = %orig;
    id rettypeactions = [rettype actions];
    NSArray *origShortcutActions = rettypeactions;
    NSArray *newShortcutActions = rettypeactions;
    NSMutableArray *newMutableShortcutActions = [newShortcutActions mutableCopy];
    int shortcutActionsObjectIndex = 0;
    
    for (id shortcutActionsObject in origShortcutActions) {
        if ([shortcutActionsObject isKindOfClass:[NSDictionary class]]){
            if ([shortcutActionsObject objectForKey:@"WFWorkflowActionIdentifier"]) {
// All shortcuts have an identifier to help identify the action (is.workflow.actions.returntohomescreen is Return to Homescreen, is.workflow.actions.exit is Exit Shortcut). You can find the default action identifiers in /System/​Library/​PrivateFrameworks/​WorkflowKit.framework/WFActions.plist
            if ([[shortcutActionsObject valueForKey:@"WFWorkflowActionIdentifier"] isEqual:@"is.workflow.actions.returntohomescreen"]) {
            NSMutableDictionary *mutableShortcutActionsObject = [shortcutActionsObject mutableCopy];
// While not demo'ed in this example, actions also have WFWorkflowActionParameters. For example, the file path in Get File is the WFGetFilePath parameter. These can also be found in WFActions.plist, or by extracting an unsigned .shortcut/.wflow file and looking to see the parameters of the action in the shortcut.
    
            [mutableShortcutActionsObject setValue:@"is.workflow.actions.exit" forKey:@"WFWorkflowActionIdentifier"];
    
            NSDictionary *newShortDict = [[NSDictionary alloc] initWithDictionary:mutableShortcutActionsObject];
            newMutableShortcutActions[shortcutActionsObjectIndex] = newShortDict;
            }
            }
        }
        shortcutActionsObjectIndex++;
    }
    
    shortcutActionsObjectIndex = 0;

    rettypeactions = [[NSArray alloc] initWithArray:newMutableShortcutActions];
    [rettype setActions:newMutableShortcutActions];
    return rettype;
}
%end

Iterating through all actions being loaded

%hook WFBundledActionProvider
-(id)createAllAvailableActions {
	id createactions = %orig;
	for (id newCreateAction in createactions) {
		NSLog(@"ZCustomShortcutActions createactions identifier: %@",[newCreateAction identifier]);
		if ([[newCreateAction identifier]isEqualToString:@"is.workflow.actions.exit"]){
			// the action being iterated has the action identifier of is.workflow.actions.exit - this means we found the exit shortcut action!
			NSLog(@"ZCustomShortcutActions exit action: %@", newCreateAction);
		}
	}

	return createactions;
}
%end

References