ApplicationShortcuts: Version 1.2, 2016-09-28

Upgraded to Swift 2.3.

Demonstrates how to use the UIApplicationShortcutItem class to provide quick access to parts of your application directly from the device's home screen. The sample shows two static shortcuts (defined in the app's Info.plist), and two dynamic shortcuts (defined in code with the UIMutableApplicationShortcutItem class). The dynamic shortcuts can be edited to change the title, subtitle and icon.

Signed-off-by: Liu Lantao <liulantao@gmail.com>
This commit is contained in:
Liu Lantao 2017-11-20 07:48:58 +08:00
parent f78eaf06a5
commit c580342ab1
No known key found for this signature in database
GPG Key ID: BF35AA0CD375679D
13 changed files with 1162 additions and 0 deletions

View File

@ -0,0 +1,332 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
5345AE1C1B97709700F65A71 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5345AE1E1B97709700F65A71 /* InfoPlist.strings */; };
53A5377E1B8CEC2600CBD3C3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A537701B8CEC2600CBD3C3 /* AppDelegate.swift */; };
53A5377F1B8CEC2600CBD3C3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 53A537711B8CEC2600CBD3C3 /* Assets.xcassets */; };
53A537801B8CEC2600CBD3C3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53A537731B8CEC2600CBD3C3 /* LaunchScreen.storyboard */; };
53A537811B8CEC2600CBD3C3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 53A537751B8CEC2600CBD3C3 /* Main.storyboard */; };
53A537871B8CEC2600CBD3C3 /* ShortcutDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A5377C1B8CEC2600CBD3C3 /* ShortcutDetailViewController.swift */; };
53A537881B8CEC2600CBD3C3 /* ShortcutsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53A5377D1B8CEC2600CBD3C3 /* ShortcutsTableViewController.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
5345AE1D1B97709700F65A71 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = "<group>"; };
5345AE1F1B97709B00F65A71 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
53A537701B8CEC2600CBD3C3 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = ApplicationShortcuts/AppDelegate.swift; sourceTree = SOURCE_ROOT; };
53A537711B8CEC2600CBD3C3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = ApplicationShortcuts/Assets.xcassets; sourceTree = SOURCE_ROOT; };
53A537741B8CEC2600CBD3C3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
53A537761B8CEC2600CBD3C3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Main.storyboard; sourceTree = "<group>"; };
53A537791B8CEC2600CBD3C3 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ApplicationShortcuts/Info.plist; sourceTree = SOURCE_ROOT; };
53A5377C1B8CEC2600CBD3C3 /* ShortcutDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShortcutDetailViewController.swift; path = ApplicationShortcuts/ShortcutDetailViewController.swift; sourceTree = SOURCE_ROOT; };
53A5377D1B8CEC2600CBD3C3 /* ShortcutsTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShortcutsTableViewController.swift; path = ApplicationShortcuts/ShortcutsTableViewController.swift; sourceTree = SOURCE_ROOT; };
EB7B7F951B8645D30063172E /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
EBD4FAAF1B83ED9C009B2114 /* AppShortcuts.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AppShortcuts.app; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
EBD4FAAC1B83ED9C009B2114 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
53A537721B8CEC2600CBD3C3 /* Base.lproj */ = {
isa = PBXGroup;
children = (
5345AE1E1B97709700F65A71 /* InfoPlist.strings */,
53A537731B8CEC2600CBD3C3 /* LaunchScreen.storyboard */,
53A537751B8CEC2600CBD3C3 /* Main.storyboard */,
);
name = Base.lproj;
path = ApplicationShortcuts/Base.lproj;
sourceTree = SOURCE_ROOT;
};
EBD4FAA61B83ED9C009B2114 = {
isa = PBXGroup;
children = (
EB7B7F951B8645D30063172E /* README.md */,
EBD4FAB11B83ED9D009B2114 /* ApplicationShortcuts */,
EBD4FAB01B83ED9D009B2114 /* Products */,
);
sourceTree = "<group>";
};
EBD4FAB01B83ED9D009B2114 /* Products */ = {
isa = PBXGroup;
children = (
EBD4FAAF1B83ED9C009B2114 /* AppShortcuts.app */,
);
name = Products;
sourceTree = "<group>";
};
EBD4FAB11B83ED9D009B2114 /* ApplicationShortcuts */ = {
isa = PBXGroup;
children = (
53A537701B8CEC2600CBD3C3 /* AppDelegate.swift */,
53A5377D1B8CEC2600CBD3C3 /* ShortcutsTableViewController.swift */,
53A5377C1B8CEC2600CBD3C3 /* ShortcutDetailViewController.swift */,
53A537791B8CEC2600CBD3C3 /* Info.plist */,
53A537711B8CEC2600CBD3C3 /* Assets.xcassets */,
53A537721B8CEC2600CBD3C3 /* Base.lproj */,
);
name = ApplicationShortcuts;
path = Tabs;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
EBD4FAAE1B83ED9C009B2114 /* ApplicationShortcuts */ = {
isa = PBXNativeTarget;
buildConfigurationList = EBD4FAC31B83ED9D009B2114 /* Build configuration list for PBXNativeTarget "ApplicationShortcuts" */;
buildPhases = (
EBD4FAAB1B83ED9C009B2114 /* Sources */,
EBD4FAAC1B83ED9C009B2114 /* Frameworks */,
EBD4FAAD1B83ED9C009B2114 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = ApplicationShortcuts;
productName = Tabs;
productReference = EBD4FAAF1B83ED9C009B2114 /* AppShortcuts.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
EBD4FAA71B83ED9C009B2114 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = Apple;
TargetAttributes = {
EBD4FAAE1B83ED9C009B2114 = {
CreatedOnToolsVersion = 7.0;
LastSwiftMigration = 0800;
};
};
};
buildConfigurationList = EBD4FAAA1B83ED9C009B2114 /* Build configuration list for PBXProject "ApplicationShortcuts" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = EBD4FAA61B83ED9C009B2114;
productRefGroup = EBD4FAB01B83ED9D009B2114 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
EBD4FAAE1B83ED9C009B2114 /* ApplicationShortcuts */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
EBD4FAAD1B83ED9C009B2114 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
53A537811B8CEC2600CBD3C3 /* Main.storyboard in Resources */,
5345AE1C1B97709700F65A71 /* InfoPlist.strings in Resources */,
53A5377F1B8CEC2600CBD3C3 /* Assets.xcassets in Resources */,
53A537801B8CEC2600CBD3C3 /* LaunchScreen.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
EBD4FAAB1B83ED9C009B2114 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
53A537871B8CEC2600CBD3C3 /* ShortcutDetailViewController.swift in Sources */,
53A5377E1B8CEC2600CBD3C3 /* AppDelegate.swift in Sources */,
53A537881B8CEC2600CBD3C3 /* ShortcutsTableViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
5345AE1E1B97709700F65A71 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
5345AE1D1B97709700F65A71 /* Base */,
5345AE1F1B97709B00F65A71 /* en */,
);
name = InfoPlist.strings;
path = ApplicationShortcuts;
sourceTree = SOURCE_ROOT;
};
53A537731B8CEC2600CBD3C3 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
53A537741B8CEC2600CBD3C3 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
53A537751B8CEC2600CBD3C3 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
53A537761B8CEC2600CBD3C3 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
EBD4FAC11B83ED9D009B2114 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
EBD4FAC21B83ED9D009B2114 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
EBD4FAC41B83ED9D009B2114 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
INFOPLIST_FILE = ApplicationShortcuts/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.ApplicationShortcuts";
PRODUCT_NAME = AppShortcuts;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 2.3;
};
name = Debug;
};
EBD4FAC51B83ED9D009B2114 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
INFOPLIST_FILE = ApplicationShortcuts/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-samplecode.ApplicationShortcuts";
PRODUCT_NAME = AppShortcuts;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 2.3;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
EBD4FAAA1B83ED9C009B2114 /* Build configuration list for PBXProject "ApplicationShortcuts" */ = {
isa = XCConfigurationList;
buildConfigurations = (
EBD4FAC11B83ED9D009B2114 /* Debug */,
EBD4FAC21B83ED9D009B2114 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
EBD4FAC31B83ED9D009B2114 /* Build configuration list for PBXNativeTarget "ApplicationShortcuts" */ = {
isa = XCConfigurationList;
buildConfigurations = (
EBD4FAC41B83ED9D009B2114 /* Debug */,
EBD4FAC51B83ED9D009B2114 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = EBD4FAA71B83ED9C009B2114 /* Project object */;
}

View File

@ -0,0 +1,147 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
The application delegate class used to manage this sample.
*/
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
// MARK: - Types
enum ShortcutIdentifier: String {
case First
case Second
case Third
case Fourth
// MARK: - Initializers
init?(fullType: String) {
guard let last = fullType.componentsSeparatedByString(".").last else { return nil }
self.init(rawValue: last)
}
// MARK: - Properties
var type: String {
return NSBundle.mainBundle().bundleIdentifier! + ".\(self.rawValue)"
}
}
// MARK: - Static Properties
static let applicationShortcutUserInfoIconKey = "applicationShortcutUserInfoIconKey"
// MARK: - Properties
/*
The app delegate must implement the window from UIApplicationDelegate
protocol to use a main storyboard file.
*/
var window: UIWindow?
/// Saved shortcut item used as a result of an app launch, used later when app is activated.
var launchedShortcutItem: UIApplicationShortcutItem?
func handleShortCutItem(shortcutItem: UIApplicationShortcutItem) -> Bool {
var handled = false
// Verify that the provided `shortcutItem`'s `type` is one handled by the application.
guard ShortcutIdentifier(fullType: shortcutItem.type) != nil else { return false }
guard let shortCutType = shortcutItem.type as String? else { return false }
switch (shortCutType) {
case ShortcutIdentifier.First.type:
// Handle shortcut 1 (static).
handled = true
break
case ShortcutIdentifier.Second.type:
// Handle shortcut 2 (static).
handled = true
break
case ShortcutIdentifier.Third.type:
// Handle shortcut 3 (dynamic).
handled = true
break
case ShortcutIdentifier.Fourth.type:
// Handle shortcut 4 (dynamic).
handled = true
break
default:
break
}
// Construct an alert using the details of the shortcut used to open the application.
let alertController = UIAlertController(title: "Shortcut Handled", message: "\"\(shortcutItem.localizedTitle)\"", preferredStyle: .Alert)
let okAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(okAction)
// Display an alert indicating the shortcut selected from the home screen.
window!.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
return handled
}
// MARK: - Application Life Cycle
func applicationDidBecomeActive(application: UIApplication) {
guard let shortcut = launchedShortcutItem else { return }
handleShortCutItem(shortcut)
launchedShortcutItem = nil
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
var shouldPerformAdditionalDelegateHandling = true
// If a shortcut was launched, display its information and take the appropriate action
if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem {
launchedShortcutItem = shortcutItem
// This will block "performActionForShortcutItem:completionHandler" from being called.
shouldPerformAdditionalDelegateHandling = false
}
// Install initial versions of our two extra dynamic shortcuts.
if let shortcutItems = application.shortcutItems where shortcutItems.isEmpty {
// Construct the items.
let shortcut3 = UIMutableApplicationShortcutItem(type: ShortcutIdentifier.Third.type, localizedTitle: "Play", localizedSubtitle: "Will Play an item", icon: UIApplicationShortcutIcon(type: .Play), userInfo: [
AppDelegate.applicationShortcutUserInfoIconKey: UIApplicationShortcutIconType.Play.rawValue
]
)
let shortcut4 = UIMutableApplicationShortcutItem(type: ShortcutIdentifier.Fourth.type, localizedTitle: "Pause", localizedSubtitle: "Will Pause an item", icon: UIApplicationShortcutIcon(type: .Pause), userInfo: [
AppDelegate.applicationShortcutUserInfoIconKey: UIApplicationShortcutIconType.Pause.rawValue
]
)
// Update the application providing the initial 'dynamic' shortcut items.
application.shortcutItems = [shortcut3, shortcut4]
}
return shouldPerformAdditionalDelegateHandling
}
/*
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.
*/
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: Bool -> Void) {
let handledShortCutItem = handleShortCutItem(shortcutItem)
completionHandler(handledShortCutItem)
}
}

View File

@ -0,0 +1,38 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,5 @@
shortcutTitle1 = "Search";
shortcutSubtitle1 = "Will search for an item";
shortcutTitle2 = "Share";
shortcutSubtitle2 = "Will share an item";

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11178" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="h4K-im-1MF">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11144"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Shortcuts-->
<scene sceneID="HLU-Zl-7DP">
<objects>
<tableViewController storyboardIdentifier="LaunchScreenTable" id="rp5-JB-a3T" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="jtZ-Ls-Rdk">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<outlet property="dataSource" destination="rp5-JB-a3T" id="6bw-hc-wS9"/>
<outlet property="delegate" destination="rp5-JB-a3T" id="O6h-eq-PaT"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Shortcuts" id="eDo-Rb-NK3"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="DQR-xt-Izu" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="785" y="413"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="mZs-3N-4em">
<objects>
<navigationController storyboardIdentifier="LaunchScreenNav" id="h4K-im-1MF" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" id="IiZ-A6-yAa">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="rp5-JB-a3T" kind="relationship" relationship="rootViewController" id="t47-xq-IlE"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="rs8-Ue-yE9" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-20" y="414"/>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11178" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="IWh-cd-MEY">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11144"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--ShortcutItemDetail-->
<scene sceneID="2kk-kx-Tj5">
<objects>
<tableViewController storyboardIdentifier="ShortcutDetail" useStoryboardIdentifierAsRestorationIdentifier="YES" id="GEw-BJ-3Vb" userLabel="ShortcutItemDetail" customClass="ShortcutDetailViewController" customModule="AppShortcuts" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="oCG-GJ-XTg">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.95686274510000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<sections>
<tableViewSection headerTitle="TITLE" id="Akh-wo-mZh">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="smf-Bz-68K">
<rect key="frame" x="0.0" y="120" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="smf-Bz-68K" id="qIR-BA-ZVS">
<frame key="frameInset" width="375" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Title" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="SOV-FH-uE9">
<color key="textColor" red="0.0" green="0.0" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
<connections>
<outlet property="delegate" destination="GEw-BJ-3Vb" id="mLH-i3-hTy"/>
</connections>
</textField>
</subviews>
<constraints>
<constraint firstItem="SOV-FH-uE9" firstAttribute="leading" secondItem="qIR-BA-ZVS" secondAttribute="leading" constant="15" id="BPa-7v-ew6"/>
<constraint firstAttribute="trailing" secondItem="SOV-FH-uE9" secondAttribute="trailing" constant="15" id="Gt4-qK-EW6"/>
<constraint firstAttribute="bottom" secondItem="SOV-FH-uE9" secondAttribute="bottom" constant="2" id="Rd7-ox-43b"/>
<constraint firstItem="SOV-FH-uE9" firstAttribute="top" secondItem="qIR-BA-ZVS" secondAttribute="top" constant="7" id="crl-og-wcV"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="SUBTITLE" id="Eig-AM-ryd">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="ZpT-Yw-DVl">
<rect key="frame" x="0.0" y="221" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ZpT-Yw-DVl" id="NXX-UF-tLO">
<frame key="frameInset" width="375" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Title" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="0Qq-Fe-aiz">
<color key="textColor" red="0.0" green="0.0" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
<connections>
<outlet property="delegate" destination="GEw-BJ-3Vb" id="M0s-6o-W1S"/>
</connections>
</textField>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="0Qq-Fe-aiz" secondAttribute="bottom" constant="2" id="8jd-kn-1Uj"/>
<constraint firstItem="0Qq-Fe-aiz" firstAttribute="leading" secondItem="NXX-UF-tLO" secondAttribute="leading" constant="15" id="Y3L-vB-uUK"/>
<constraint firstItem="0Qq-Fe-aiz" firstAttribute="top" secondItem="NXX-UF-tLO" secondAttribute="top" constant="7" id="ile-Kf-YpT"/>
<constraint firstAttribute="trailing" secondItem="0Qq-Fe-aiz" secondAttribute="trailing" constant="15" id="zXE-09-G5c"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="ICON" id="Sbn-Ds-ZUw">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="123" id="cjY-6r-rSI">
<rect key="frame" x="0.0" y="322" width="375" height="123"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="cjY-6r-rSI" id="Fqw-Yc-YPr">
<frame key="frameInset" width="375" height="122"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<pickerView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ysH-Tl-DdL">
<connections>
<outlet property="dataSource" destination="GEw-BJ-3Vb" id="O1n-ov-vzw"/>
<outlet property="delegate" destination="GEw-BJ-3Vb" id="SyU-qj-KF4"/>
</connections>
</pickerView>
</subviews>
<constraints>
<constraint firstAttribute="bottomMargin" secondItem="ysH-Tl-DdL" secondAttribute="bottom" id="kLI-8V-F5x"/>
<constraint firstItem="ysH-Tl-DdL" firstAttribute="top" secondItem="Fqw-Yc-YPr" secondAttribute="topMargin" constant="6" id="kSg-X8-sfh"/>
<constraint firstAttribute="trailingMargin" secondItem="ysH-Tl-DdL" secondAttribute="trailing" id="lkB-dl-9es"/>
<constraint firstAttribute="leadingMargin" secondItem="ysH-Tl-DdL" secondAttribute="leading" id="xzA-Tj-FDN"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
<connections>
<outlet property="dataSource" destination="GEw-BJ-3Vb" id="wPU-Vk-mun"/>
<outlet property="delegate" destination="GEw-BJ-3Vb" id="7KB-nf-2JB"/>
</connections>
</tableView>
<navigationItem key="navigationItem" id="72M-zG-D7M">
<barButtonItem key="leftBarButtonItem" title="Cancel" id="Wg1-Gx-Nzw">
<connections>
<segue destination="Aaj-4d-d5m" kind="unwind" identifier="ShortcutDetailCancelled" unwindAction="cancel:" id="Znr-N3-kET"/>
</connections>
</barButtonItem>
<barButtonItem key="rightBarButtonItem" systemItem="done" id="niZ-q1-T49">
<connections>
<segue destination="7ye-q1-REg" kind="unwind" identifier="ShortcutDetailUpdated" unwindAction="done:" id="okd-5n-xee"/>
</connections>
</barButtonItem>
</navigationItem>
<connections>
<outlet property="doneButton" destination="niZ-q1-T49" id="MiO-Q1-G67"/>
<outlet property="pickerView" destination="ysH-Tl-DdL" id="bZH-ao-vqI"/>
<outlet property="subtitleTextField" destination="0Qq-Fe-aiz" id="ebA-gA-kLZ"/>
<outlet property="titleTextField" destination="SOV-FH-uE9" id="XkP-0l-3tp"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="XW5-Qg-RSe" userLabel="First Responder" sceneMemberID="firstResponder"/>
<exit id="Aaj-4d-d5m" userLabel="Exit" sceneMemberID="exit"/>
</objects>
<point key="canvasLocation" x="1699" y="-690"/>
</scene>
<!--ShortcutItemsTableViewController-->
<scene sceneID="e3g-S6-Dq3">
<objects>
<tableViewController storyboardIdentifier="ShortcutsTableViewController" title="Third View Controller" useStoryboardIdentifierAsRestorationIdentifier="YES" id="0nb-dB-Thb" userLabel="ShortcutItemsTableViewController" customClass="ShortcutsTableViewController" customModule="AppShortcuts" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="CtH-SO-5Mi">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="CellID" textLabel="v39-LU-kIp" detailTextLabel="bQL-nM-M0m" style="IBUITableViewCellStyleSubtitle" id="tcO-Gg-0gM">
<frame key="frameInset" minY="92" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="tcO-Gg-0gM" id="usU-hY-H3V">
<frame key="frameInset" width="342" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="v39-LU-kIp">
<frame key="frameInset" minX="15" minY="5" width="32" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Subtitle" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="bQL-nM-M0m">
<frame key="frameInset" minX="15" minY="25" width="41" height="14"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="GEw-BJ-3Vb" kind="show" identifier="ShowShortcutDetail" id="f4U-Br-Wkx"/>
</connections>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="0nb-dB-Thb" id="b6i-pz-Z4O"/>
<outlet property="delegate" destination="0nb-dB-Thb" id="zcO-wS-Eaq"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Shortcuts" id="ogi-vv-V8e"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="wV3-ZN-AWJ" userLabel="First Responder" sceneMemberID="firstResponder"/>
<exit id="7ye-q1-REg" userLabel="Exit" sceneMemberID="exit"/>
</objects>
<point key="canvasLocation" x="792" y="-690"/>
</scene>
<!--ShortCutsNavController-->
<scene sceneID="4ji-UO-XKX">
<objects>
<navigationController storyboardIdentifier="RootViewController" automaticallyAdjustsScrollViewInsets="NO" useStoryboardIdentifierAsRestorationIdentifier="YES" id="IWh-cd-MEY" userLabel="ShortCutsNavController" sceneMemberID="viewController">
<toolbarItems/>
<navigationItem key="navigationItem" id="y6E-Kx-dxS"/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="zs5-f8-XoS">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="0nb-dB-Thb" kind="relationship" relationship="rootViewController" id="aEf-WQ-82y"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="8mE-55-YlQ" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="32" y="-690"/>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,83 @@
<?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>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationShortcutItems</key>
<array>
<dict>
<key>UIApplicationShortcutItemIconType</key>
<string>UIApplicationShortcutIconTypeSearch</string>
<key>UIApplicationShortcutItemSubtitle</key>
<string>shortcutSubtitle1</string>
<key>UIApplicationShortcutItemTitle</key>
<string>shortcutTitle1</string>
<key>UIApplicationShortcutItemType</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).First</string>
<key>UIApplicationShortcutItemUserInfo</key>
<dict>
<key>firstShorcutKey1</key>
<string>firstShortcutKeyValue1</string>
</dict>
</dict>
<dict>
<key>UIApplicationShortcutItemIconType</key>
<string>UIApplicationShortcutIconTypeShare</string>
<key>UIApplicationShortcutItemSubtitle</key>
<string>shortcutSubtitle2</string>
<key>UIApplicationShortcutItemTitle</key>
<string>shortcutTitle2</string>
<key>UIApplicationShortcutItemType</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).Second</string>
<key>UIApplicationShortcutItemUserInfo</key>
<dict>
<key>secondShortcutKey1</key>
<string>secondShortcutValue1</string>
</dict>
</dict>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIStatusBarTintParameters</key>
<dict>
<key>UINavigationBar</key>
<dict>
<key>Style</key>
<string>UIBarStyleDefault</string>
<key>Translucent</key>
<false/>
</dict>
</dict>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@ -0,0 +1,115 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
The detail view controller for viewing and editing shortcut information (localized title, localized subtitle, and icon)
*/
import UIKit
class ShortcutDetailViewController: UITableViewController {
// MARK: - Properties
@IBOutlet weak var titleTextField: UITextField!
@IBOutlet weak var subtitleTextField: UITextField!
@IBOutlet weak var pickerView: UIPickerView!
@IBOutlet weak var doneButton: UIBarButtonItem!
var pickerItems = ["Compose", "Play", "Pause", "Add", "Location", "Search", "Share"]
/// Used to share information between this controller and its parent.
var shortcutItem: UIApplicationShortcutItem?
/// The observer token for the `UITextFieldDidChangeNotification`.
var textFieldObserverToken: NSObjectProtocol?
// MARK: - Object Life Cycle
deinit {
guard let token = textFieldObserverToken else { return }
NSNotificationCenter.defaultCenter().removeObserver(token)
}
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
// Initialize the UI to reflect the values of the `shortcutItem`.
guard let selectedShortcutItem = shortcutItem else {
fatalError("The `selectedShortcutItem` was not set.")
}
title = selectedShortcutItem.localizedTitle
titleTextField.text = selectedShortcutItem.localizedTitle
subtitleTextField.text = selectedShortcutItem.localizedSubtitle
// Extract the raw value representing the icon from the userInfo dictionary, if provided.
guard let iconRawValue = selectedShortcutItem.userInfo?[AppDelegate.applicationShortcutUserInfoIconKey] as? Int else { return }
// Select the matching row in the picker for the icon type.
let iconType = iconTypeForSelectedRow(iconRawValue)
// The `iconType` returned may not align to the `iconRawValue` so use the `iconType`'s `rawValue`.
pickerView.selectRow(iconType.rawValue, inComponent:0, animated:false)
let notificationCenter = NSNotificationCenter.defaultCenter()
textFieldObserverToken = notificationCenter.addObserverForName(UITextFieldTextDidChangeNotification, object: nil, queue: nil) { [weak self] _ in
guard let strongSelf = self else { return }
// You cannot dismiss the view controller without a valid shortcut title.
let titleTextLength = strongSelf.titleTextField.text?.characters.count ?? 0
strongSelf.doneButton.enabled = titleTextLength > 0
}
}
// MARK: - UITextFieldDelegate
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
// MARK: - UIPickerViewDataSource
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerItems.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerItems[row]
}
/// Constructs a UIApplicationShortcutIconType based on the integer result from our picker.
func iconTypeForSelectedRow(row: Int) -> UIApplicationShortcutIconType {
return UIApplicationShortcutIconType(rawValue: row) ?? .Compose
}
// MARK: - UIStoryboardSegue Handling
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let selectedShortcutItem = shortcutItem else {
fatalError("The `selectedShortcutItem` was not set.")
}
if segue.identifier == "ShortcutDetailUpdated" {
// In the updated case, create a shortcut item to represent the final state of the view controller.
let iconType = iconTypeForSelectedRow(pickerView.selectedRowInComponent(0))
let icon = UIApplicationShortcutIcon(type: iconType)
shortcutItem = UIApplicationShortcutItem(type: selectedShortcutItem.type, localizedTitle: titleTextField.text ?? "", localizedSubtitle: subtitleTextField.text, icon: icon, userInfo: [
AppDelegate.applicationShortcutUserInfoIconKey: pickerView.selectedRowInComponent(0)
]
)
}
}
}

View File

@ -0,0 +1,126 @@
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this samples licensing information
Abstract:
The primary view controller listing the mutable shortcuts registered for this sample.
*/
import UIKit
class ShortcutsTableViewController: UITableViewController {
// MARK: - Properties
/// Pre-defined shortcuts; retrieved from the Info.plist, lazily.
lazy var staticShortcuts: [UIApplicationShortcutItem] = {
// Obtain the `UIApplicationShortcutItems` array from the Info.plist. If unavailable, there are no static shortcuts.
guard let shortcuts = NSBundle.mainBundle().infoDictionary?["UIApplicationShortcutItems"] as? [[String: NSObject]] else { return [] }
// Use `flatMap(_:)` to process each dictionary into a `UIApplicationShortcutItem`, if possible.
let shortcutItems = shortcuts.flatMap { shortcut -> [UIApplicationShortcutItem] in
// The `UIApplicationShortcutItemType` and `UIApplicationShortcutItemTitle` keys are required to successfully create a `UIApplicationShortcutItem`.
guard let shortcutType = shortcut["UIApplicationShortcutItemType"] as? String,
let shortcutTitle = shortcut["UIApplicationShortcutItemTitle"] as? String else { return [] }
// Get the localized title.
var localizedShortcutTitle = shortcutTitle
if let localizedTitle = NSBundle.mainBundle().localizedInfoDictionary?[shortcutTitle] as? String {
localizedShortcutTitle = localizedTitle
}
/*
The `UIApplicationShortcutItemSubtitle` key is optional. If it
exists, get the localized version.
*/
var localizedShortcutSubtitle: String?
if let shortcutSubtitle = shortcut["UIApplicationShortcutItemSubtitle"] as? String {
localizedShortcutSubtitle = NSBundle.mainBundle().localizedInfoDictionary?[shortcutSubtitle] as? String
}
return [
UIApplicationShortcutItem(type: shortcutType, localizedTitle: localizedShortcutTitle, localizedSubtitle: localizedShortcutSubtitle, icon: nil, userInfo: nil)
]
}
return shortcutItems
}()
/// Shortcuts defined by the application and modifiable based on application state.
lazy var dynamicShortcuts = UIApplication.sharedApplication().shortcutItems ?? []
// MARK: - UITableViewDataSource
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return ["Static", "Dynamic"][section]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return section == 0 ? staticShortcuts.count : dynamicShortcuts.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CellID", forIndexPath: indexPath)
let shortcut: UIApplicationShortcutItem
if indexPath.section == 0 {
// Static shortcuts (cannot be edited).
shortcut = staticShortcuts[indexPath.row]
cell.accessoryType = .None
cell.selectionStyle = .None
}
else {
// Dynamic shortcuts.
shortcut = dynamicShortcuts[indexPath.row]
}
cell.textLabel?.text = shortcut.localizedTitle
cell.detailTextLabel?.text = shortcut.localizedSubtitle
return cell
}
// MARK: - Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Supply the `shortcutItem` matching the selected row from the data source.
if segue.identifier == "ShowShortcutDetail" {
guard let indexPath = tableView.indexPathForSelectedRow,
let controller = segue.destinationViewController as? ShortcutDetailViewController else { return }
controller.shortcutItem = dynamicShortcuts[indexPath.row]
}
}
override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {
// Block navigating to detail view controller for static shortcuts (which are not editable).
guard let selectedIndexPath = tableView.indexPathForSelectedRow else { return false }
return selectedIndexPath.section > 0
}
// MARK: - Actions
// Unwind segue action called when the user taps 'Done' after navigating to the detail controller.
@IBAction func done(sender: UIStoryboardSegue) {
// Obtain the edited shortcut from our source view controller.
guard let sourceViewController = sender.sourceViewController as? ShortcutDetailViewController,
let selected = tableView.indexPathForSelectedRow,
let updatedShortcutItem = sourceViewController.shortcutItem else { return }
// Update our data source.
dynamicShortcuts[selected.row] = updatedShortcutItem
// Update the application's `shortcutItems`.
UIApplication.sharedApplication().shortcutItems = dynamicShortcuts
tableView.reloadRowsAtIndexPaths([selected], withRowAnimation: .Automatic)
}
// Unwind segue action called when the user taps 'Cancel' after navigating to the detail controller.
@IBAction func cancel(sender: UIStoryboardSegue) {}
}

View File

@ -0,0 +1,5 @@
shortcutTitle1 = "Search";
shortcutSubtitle1 = "Will search for an item";
shortcutTitle2 = "Share";
shortcutSubtitle2 = "Will share an item";

View File

@ -0,0 +1,42 @@
Sample code project: ApplicationShortcuts: Using UIApplicationShortcutItem
Version: 1.2
IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2016 Apple Inc. All Rights Reserved.

View File

@ -0,0 +1,20 @@
# Application Shortcuts: Using UIApplicationShortcutItem
## Summary
Demonstrates how to use the UIApplicationShortcutItem class in your application so users can quickly access parts of an application through “Quick actions” from the Home screen.
It implements four different shortcuts, two static defined (UIApplicationShortcutItem) in your Info.pist, two dynamic or mutable (UIMutableApplicationShortcutItem) defined through code. The mutable shortcuts can be edited to change that title, subtitle and icon.
IMPORTANT: This sample should be run on an iPhone 6s or 6s Plus device. The iOS simulator will allow use of the shortcuts through its Hardware -> Touch Pressure menu, which requires a Trackpad.
## Requirements
### Build
iOS 10.0 SDK, Xcode 8.0
### Runtime
iOS 9.0
Copyright (C) 2015-2016 Apple Inc. All rights reserved.