Obj-C 中的 3D Touch Home 快捷方式
3D Touch Home Shortcuts In Obj-C
我所有的应用程序目前都是用 Obj-C 编写的。 link https://developer.apple.com/library/content/samplecode/ApplicationShortcuts/Introduction/Intro.html#//apple_ref/doc/uid/TP40016545 3D Touch 实现主屏幕快捷方式的示例代码完全编译在Swift 中。任何人看到 Obj-C 的文档,所以我不必通过我的 AppDelegate 并翻译它吗?
更新:
在 Info.plist 中添加所有快捷方式后,我在 AppDelegate.m 中添加:
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
UINavigationController *nav = (UINavigationController *) self.tabBarController.selectedViewController;
NSLog(@"%@", shortcutItem.type);
if ([shortcutItem.type isEqualToString:@"com.316apps.iPrayed.addPrayerRequest"]) {
Requests *gonow = [[Requests alloc] init];
[nav pushViewController:gonow animated:YES];
}
if ([shortcutItem.type isEqualToString:@"com.316apps.iPrayed.addPrayer"]) {
PrayerStats *controller = [[PrayerStats alloc] init];
[nav pushViewController:controller animated:YES];
}
if ([shortcutItem.type isEqualToString:@"com.316apps.iPrayed.addFast"]) {
FastStats *controller1 = [[FastStats alloc] init];
[nav pushViewController:controller1 animated:YES];
}
if ([shortcutItem.type isEqualToString:@"com.316apps.iPrayed.addStudy"]) {
StudyStats *controller2 = [[StudyStats alloc] init];
[nav pushViewController:controller2 animated:YES];
}
}
这允许它工作,无需放入任何其他方法,或向 didFinishLaunchingWithOptions 添加任何内容。
用户可以在两种状态下通过快速操作打开应用程序。
TL;DR
无论快速操作完成时应用程序的状态如何,您总是在做同样的事情,这就是为什么您只需要覆盖 application:performActionForShortcutItem:completionHandler:
所以如果您想做不同的事情,那么您需要处理他们在两个地方,如果不是那么只是覆盖就足够了。
一个是应用程序是否被终止 运行 在后台我们在启动时获取快捷方式信息。
另一种情况是应用程序 运行 在后台,我们可以在后台获取有关新应用程序委托方法的快捷方式信息。
要在后台处理这些快速操作快捷方式,您需要在 App Delegate 上覆盖此方法:
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler
而不是 运行 在您的
后台(被杀死)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
或
-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
您应该检查应用程序是否通过快速操作启动:
UIApplicationShortcutItem *shortcutItem = [launchOptions objectForKey:UIApplicationLaunchOptionsShortcutItemKey];
(Link to related Apple Documentation)
引用自官方 Apple 文档
It’s your responsibility to ensure the system calls this method
conditionally, depending on whether or not one of your app launch
methods (application:willFinishLaunchingWithOptions: or
application:didFinishLaunchingWithOptions:) has already handled a
quick action invocation. The system calls a launch method (before
calling this method) when a user selects a quick action for your app
and your app launches instead of activating.
The requested quick action might employ code paths different than
those used otherwise when your app launches. For example, say your app
normally launches to display view A, but your app was launched in
response to a quick action that needs view B. To handle such cases,
check, on launch, whether your app is being launched via a quick
action. Perform this check in your
application:willFinishLaunchingWithOptions: or
application:didFinishLaunchingWithOptions: method by checking for the
UIApplicationLaunchOptionsShortcutItemKey launch option key. The
UIApplicationShortcutItem object is available as the value of the
launch option key.
If you find that your app was indeed launched using a quick action,
perform the requested quick action within the launch method and return
a value of NO from that method. When you return a value of NO, the
system does not call the
application:performActionForShortcutItem:completionHandler: method.
如果您查看为 apple 提供的示例代码,您会发现他们建议您编写一个方法来处理您的快捷方式项目,以便您可以在所有三个地方处理它:
application: performActionForShortcutItem
,
application: didFinishLaunchingWithOptions
和
willFinishLaunchingWithOptions
我所做的一个例子是:
- (BOOL)handleShortCutItem:(UIApplicationShortcutItem *)shortcutItem {
BOOL handled = NO;
if (shortcutItem == nil) {
return handled;
}
if ([shortcutItem.type isEqualToString:kFavoritesQuickAction]) {
handled = YES;
}
if (handled) {
// do action here
}
return handled;
}
那么你只要在任何需要快捷方式的地方调用这个方法即可。这应该对您有所帮助!
我制作了一个 objective-c 主屏幕快速操作演示项目。
3D touch home quick action demo : https://github.com/dakeshi/3D_Touch_HomeQuickAction
Demo项目实现了没有Info.plist文件的静态快速操作,以避免在首次启动应用程序之前出现意外情况。
您可以轻松地将其更改为动态快速操作。
如苹果文档中所述,您可以在 application:didFinishLaunchingWithOptions: 方法中处理快速操作。在这种情况下,您应该 return 否阻止调用 application:performActionForShortcutItem:completionHandler: 方法。
执行以下 3 个简单步骤:
第 1 步: 在 AppDelegate
class 中编写以下方法来配置动态快捷方式项。
注意:如果您希望它是静态的,您可以在 info.plist 中配置快捷方式项目。
(参考Apple documentation.)
/**
* @brief config dynamic shortcutItems
* @discussion after first launch, users can see dynamic shortcutItems
*/
- (void)configDynamicShortcutItems {
// config image shortcut items
// if you want to use custom image in app bundles, use iconWithTemplateImageName method
UIApplicationShortcutIcon *shortcutSearchIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeSearch];
UIApplicationShortcutIcon *shortcutFavoriteIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeFavorite];
UIApplicationShortcutItem *shortcutSearch = [[UIApplicationShortcutItem alloc]
initWithType:@"com.sarangbang.QuickAction.Search"
localizedTitle:@"Search"
localizedSubtitle:nil
icon:shortcutSearchIcon
userInfo:nil];
UIApplicationShortcutItem *shortcutFavorite = [[UIApplicationShortcutItem alloc]
initWithType:@"com.sarangbang.QuickAction.Favorite"
localizedTitle:@"Favorite"
localizedSubtitle:nil
icon:shortcutFavoriteIcon
userInfo:nil];
// add all items to an array
NSArray *items = @[shortcutSearch, shortcutFavorite];
// add the array to our app
[UIApplication sharedApplication].shortcutItems = items;
}
第 2 步: 在 AppDelegate
class application didFinishLaunchingWithOptions
方法中编写下面的代码。
// UIApplicationShortcutItem is available in iOS 9 or later.
if([[UIApplicationShortcutItem class] respondsToSelector:@selector(new)]){
[self configDynamicShortcutItems];
// If a shortcut was launched, display its information and take the appropriate action
UIApplicationShortcutItem *shortcutItem = [launchOptions objectForKeyedSubscript:UIApplicationLaunchOptionsShortcutItemKey];
if(shortcutItem)
{
// When the app launch at first time, this block can not called.
//App launch process with quick actions
[self handleShortCutItem:shortcutItem];
}else{
// normal app launch process without quick action
}
}
第 3 步: 在 AppDelegate
class.
中写下委托方法和完成处理程序
/*
Called when the user activates your application by selecting a shortcut on the home screen, except when
application(_:,willFinishLaunchingWithOptions:) or application(_:didFinishLaunchingWithOptions) returns `false`.
You should handle the shortcut in those callbacks and return `false` if possible. In that case, this
callback is used if your application is already launched in the background.
*/
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler{
BOOL handledShortCutItem = [self handleShortCutItem:shortcutItem];
completionHandler(handledShortCutItem);
}
/**
* @brief handle shortcut item depend on its type
*
* @param shortcutItem shortcutItem selected shortcut item with quick action.
*
* @return return BOOL description
*/
- (BOOL)handleShortCutItem : (UIApplicationShortcutItem *)shortcutItem{
BOOL handled = NO;
NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;
NSString *shortcutSearch = [NSString stringWithFormat:@"%@.Search", bundleId];
NSString *shortcutFavorite = [NSString stringWithFormat:@"%@.Favorite", bundleId];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
if ([shortcutItem.type isEqualToString:shortcutSearch]) {
handled = YES;
SecondViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"secondVC"];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
}
else if ([shortcutItem.type isEqualToString:shortcutFavorite]) {
handled = YES;
ThirdViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"thirdVC"];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
}
return handled;
}
它适用于 swift 3 和 4(仅适用于主屏幕快捷方式)
//Add plist items as show in image and write following method in Appdelegate
//3D Touch Method shortcuts from home screen
func application(_ application: UIApplication, performActionFor shortcutItem:UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
if shortcutItem.type == "Share" {
//handle action Share
let alert = UIAlertController(title: "3D touch Share", message: "Yahoo!!! 3D touch is working", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.window?.rootViewController?.present(alert,animated: true,completion: nil)
completionHandler(true)
} else if shortcutItem.type == "Logout" {
//handle action Type02
let alert = UIAlertController(title: "3D touch Logout", message: "Yahoo!!! 3D touch is working", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.window?.rootViewController?.present(alert,animated: true,completion: nil)
completionHandler(true)
} else {
completionHandler(false)
}
}
我所有的应用程序目前都是用 Obj-C 编写的。 link https://developer.apple.com/library/content/samplecode/ApplicationShortcuts/Introduction/Intro.html#//apple_ref/doc/uid/TP40016545 3D Touch 实现主屏幕快捷方式的示例代码完全编译在Swift 中。任何人看到 Obj-C 的文档,所以我不必通过我的 AppDelegate 并翻译它吗?
更新:
在 Info.plist 中添加所有快捷方式后,我在 AppDelegate.m 中添加:
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
UINavigationController *nav = (UINavigationController *) self.tabBarController.selectedViewController;
NSLog(@"%@", shortcutItem.type);
if ([shortcutItem.type isEqualToString:@"com.316apps.iPrayed.addPrayerRequest"]) {
Requests *gonow = [[Requests alloc] init];
[nav pushViewController:gonow animated:YES];
}
if ([shortcutItem.type isEqualToString:@"com.316apps.iPrayed.addPrayer"]) {
PrayerStats *controller = [[PrayerStats alloc] init];
[nav pushViewController:controller animated:YES];
}
if ([shortcutItem.type isEqualToString:@"com.316apps.iPrayed.addFast"]) {
FastStats *controller1 = [[FastStats alloc] init];
[nav pushViewController:controller1 animated:YES];
}
if ([shortcutItem.type isEqualToString:@"com.316apps.iPrayed.addStudy"]) {
StudyStats *controller2 = [[StudyStats alloc] init];
[nav pushViewController:controller2 animated:YES];
}
}
这允许它工作,无需放入任何其他方法,或向 didFinishLaunchingWithOptions 添加任何内容。
用户可以在两种状态下通过快速操作打开应用程序。
TL;DR
无论快速操作完成时应用程序的状态如何,您总是在做同样的事情,这就是为什么您只需要覆盖 application:performActionForShortcutItem:completionHandler:
所以如果您想做不同的事情,那么您需要处理他们在两个地方,如果不是那么只是覆盖就足够了。
一个是应用程序是否被终止 运行 在后台我们在启动时获取快捷方式信息。
另一种情况是应用程序 运行 在后台,我们可以在后台获取有关新应用程序委托方法的快捷方式信息。
要在后台处理这些快速操作快捷方式,您需要在 App Delegate 上覆盖此方法:
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler
而不是 运行 在您的
后台(被杀死)- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
或
-(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
您应该检查应用程序是否通过快速操作启动:
UIApplicationShortcutItem *shortcutItem = [launchOptions objectForKey:UIApplicationLaunchOptionsShortcutItemKey];
(Link to related Apple Documentation) 引用自官方 Apple 文档
It’s your responsibility to ensure the system calls this method conditionally, depending on whether or not one of your app launch methods (application:willFinishLaunchingWithOptions: or application:didFinishLaunchingWithOptions:) has already handled a quick action invocation. The system calls a launch method (before calling this method) when a user selects a quick action for your app and your app launches instead of activating.
The requested quick action might employ code paths different than those used otherwise when your app launches. For example, say your app normally launches to display view A, but your app was launched in response to a quick action that needs view B. To handle such cases, check, on launch, whether your app is being launched via a quick action. Perform this check in your application:willFinishLaunchingWithOptions: or application:didFinishLaunchingWithOptions: method by checking for the UIApplicationLaunchOptionsShortcutItemKey launch option key. The UIApplicationShortcutItem object is available as the value of the launch option key.
If you find that your app was indeed launched using a quick action, perform the requested quick action within the launch method and return a value of NO from that method. When you return a value of NO, the system does not call the application:performActionForShortcutItem:completionHandler: method.
如果您查看为 apple 提供的示例代码,您会发现他们建议您编写一个方法来处理您的快捷方式项目,以便您可以在所有三个地方处理它:
application: performActionForShortcutItem
,application: didFinishLaunchingWithOptions
和willFinishLaunchingWithOptions
我所做的一个例子是:
- (BOOL)handleShortCutItem:(UIApplicationShortcutItem *)shortcutItem {
BOOL handled = NO;
if (shortcutItem == nil) {
return handled;
}
if ([shortcutItem.type isEqualToString:kFavoritesQuickAction]) {
handled = YES;
}
if (handled) {
// do action here
}
return handled;
}
那么你只要在任何需要快捷方式的地方调用这个方法即可。这应该对您有所帮助!
我制作了一个 objective-c 主屏幕快速操作演示项目。
3D touch home quick action demo : https://github.com/dakeshi/3D_Touch_HomeQuickAction
Demo项目实现了没有Info.plist文件的静态快速操作,以避免在首次启动应用程序之前出现意外情况。 您可以轻松地将其更改为动态快速操作。
如苹果文档中所述,您可以在 application:didFinishLaunchingWithOptions: 方法中处理快速操作。在这种情况下,您应该 return 否阻止调用 application:performActionForShortcutItem:completionHandler: 方法。
执行以下 3 个简单步骤:
第 1 步: 在 AppDelegate
class 中编写以下方法来配置动态快捷方式项。
注意:如果您希望它是静态的,您可以在 info.plist 中配置快捷方式项目。 (参考Apple documentation.)
/**
* @brief config dynamic shortcutItems
* @discussion after first launch, users can see dynamic shortcutItems
*/
- (void)configDynamicShortcutItems {
// config image shortcut items
// if you want to use custom image in app bundles, use iconWithTemplateImageName method
UIApplicationShortcutIcon *shortcutSearchIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeSearch];
UIApplicationShortcutIcon *shortcutFavoriteIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeFavorite];
UIApplicationShortcutItem *shortcutSearch = [[UIApplicationShortcutItem alloc]
initWithType:@"com.sarangbang.QuickAction.Search"
localizedTitle:@"Search"
localizedSubtitle:nil
icon:shortcutSearchIcon
userInfo:nil];
UIApplicationShortcutItem *shortcutFavorite = [[UIApplicationShortcutItem alloc]
initWithType:@"com.sarangbang.QuickAction.Favorite"
localizedTitle:@"Favorite"
localizedSubtitle:nil
icon:shortcutFavoriteIcon
userInfo:nil];
// add all items to an array
NSArray *items = @[shortcutSearch, shortcutFavorite];
// add the array to our app
[UIApplication sharedApplication].shortcutItems = items;
}
第 2 步: 在 AppDelegate
class application didFinishLaunchingWithOptions
方法中编写下面的代码。
// UIApplicationShortcutItem is available in iOS 9 or later.
if([[UIApplicationShortcutItem class] respondsToSelector:@selector(new)]){
[self configDynamicShortcutItems];
// If a shortcut was launched, display its information and take the appropriate action
UIApplicationShortcutItem *shortcutItem = [launchOptions objectForKeyedSubscript:UIApplicationLaunchOptionsShortcutItemKey];
if(shortcutItem)
{
// When the app launch at first time, this block can not called.
//App launch process with quick actions
[self handleShortCutItem:shortcutItem];
}else{
// normal app launch process without quick action
}
}
第 3 步: 在 AppDelegate
class.
/*
Called when the user activates your application by selecting a shortcut on the home screen, except when
application(_:,willFinishLaunchingWithOptions:) or application(_:didFinishLaunchingWithOptions) returns `false`.
You should handle the shortcut in those callbacks and return `false` if possible. In that case, this
callback is used if your application is already launched in the background.
*/
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler{
BOOL handledShortCutItem = [self handleShortCutItem:shortcutItem];
completionHandler(handledShortCutItem);
}
/**
* @brief handle shortcut item depend on its type
*
* @param shortcutItem shortcutItem selected shortcut item with quick action.
*
* @return return BOOL description
*/
- (BOOL)handleShortCutItem : (UIApplicationShortcutItem *)shortcutItem{
BOOL handled = NO;
NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;
NSString *shortcutSearch = [NSString stringWithFormat:@"%@.Search", bundleId];
NSString *shortcutFavorite = [NSString stringWithFormat:@"%@.Favorite", bundleId];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
if ([shortcutItem.type isEqualToString:shortcutSearch]) {
handled = YES;
SecondViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"secondVC"];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
}
else if ([shortcutItem.type isEqualToString:shortcutFavorite]) {
handled = YES;
ThirdViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"thirdVC"];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
}
return handled;
}
它适用于 swift 3 和 4(仅适用于主屏幕快捷方式)
//Add plist items as show in image and write following method in Appdelegate
//3D Touch Method shortcuts from home screen
func application(_ application: UIApplication, performActionFor shortcutItem:UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
if shortcutItem.type == "Share" {
//handle action Share
let alert = UIAlertController(title: "3D touch Share", message: "Yahoo!!! 3D touch is working", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.window?.rootViewController?.present(alert,animated: true,completion: nil)
completionHandler(true)
} else if shortcutItem.type == "Logout" {
//handle action Type02
let alert = UIAlertController(title: "3D touch Logout", message: "Yahoo!!! 3D touch is working", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.window?.rootViewController?.present(alert,animated: true,completion: nil)
completionHandler(true)
} else {
completionHandler(false)
}
}