Oak
Oak

Reputation: 165

iOS Action Extension Sample Code Not Working

The iOS Action Extension sample code does not seem to work.

  1. In xCode, I create a new Swift project and choose Single View Application.

  2. Then I select File > New > Target, and choose Action Extension. I enter a name, choose Swift, and select Action Type: No User Interface

  3. Then I test the extension by running the project and choosing Safari. I navigate to the Google website.

  4. I enable the extension via the Actions icon in Safari. Then I press the extension icon to run it in Safari, but nothing happens.

  5. I expect the webpage background color to change, as the Action.js code, which is supposed to be run, sets the background color: document.body.style.background= "blue"

It is as if the Action.js code never gets called. All the code is from the default Action Extension template, and has not been modified.

Info.plist

<key>NSExtension</key>
    <dict>
        <key>NSExtensionAttributes</key>
        <dict>
            <key>NSExtensionActivationRule</key>
            <dict>
                <key>NSExtensionActivationSupportsFileWithMaxCount</key>
                <integer>0</integer>
                <key>NSExtensionActivationSupportsImageWithMaxCount</key>
                <integer>0</integer>
                <key>NSExtensionActivationSupportsMovieWithMaxCount</key>
                <integer>0</integer>
                <key>NSExtensionActivationSupportsText</key>
                <false/>
                <key>NSExtensionActivationSupportsWebPageWithMaxCount</key>
                <integer>1</integer>
            </dict>
            <key>NSExtensionJavaScriptPreprocessingFile</key>
            <string>Action</string>
        </dict>
        <key>NSExtensionPointIdentifier</key>
        <string>com.apple.services</string>
        <key>NSExtensionPrincipalClass</key>
        <string>$(PRODUCT_MODULE_NAME).ActionRequestHandler</string>
    </dict>

Upvotes: 1

Views: 1696

Answers (2)

Tom Harrington
Tom Harrington

Reputation: 70936

There's a bug in the Swift version of Xcode's project template for this kind of extension, apparently because of an error when someone was converting from Objective-C to Swift.

To make a long story short: the line that reads "found = true" is in the wrong place. This causes the method doneWithResults to be called twice when it should only be called once. On the first call it sets self.extensionContext = nil. On the second call it tries to use self.extensionContext and throws an exception due to unwrapping a nil optional. But the exception message gets swallowed by the extension system, so there are no clues.

If you change this code in the project template:

itemProvider.loadItemForTypeIdentifier(String(kUTTypePropertyList), options: nil, completionHandler: { (item, error) in
    let dictionary = item as! [String: AnyObject]
    NSOperationQueue.mainQueue().addOperationWithBlock {
        self.itemLoadCompletedWithPreprocessingResults(dictionary[NSExtensionJavaScriptPreprocessingResultsKey] as! [NSObject: AnyObject])
    }
    found = true
})

to look like this:

itemProvider.loadItemForTypeIdentifier(String(kUTTypePropertyList), options: nil, completionHandler: { (item, error) in
    let dictionary = item as! [String: AnyObject]
    NSOperationQueue.mainQueue().addOperationWithBlock {
        self.itemLoadCompletedWithPreprocessingResults(dictionary[NSExtensionJavaScriptPreprocessingResultsKey] as! [NSObject: AnyObject])
    }
})
found = true

...then it works as expected.

I filed the bug rdar://22482042 about this and I encourage you to file one as well.

Upvotes: 5

Oak
Oak

Reputation: 165

I found a solution: create the project and app extension in Objective C, instead of Swift, and everything works fine. So apparently there is a bug in the Swift implementation.

Upvotes: 0

Related Questions