I'd like to receive files in my app, but only certain UIScenes can receive a file. How do I tell the system which of the UIScenes in my app can receive that file? How does the system pick a scene?
I've tried using UISceneActivationConditions(). Here is what I put in the scenes that can receive files:
var preferredActivatePredicates = [NSPredicate]()
var canActivatePredicates = [NSPredicate]()
// Any scene *can* be activated at any time
canActivatePredicates.append(NSPredicate(value: true))
if hasWriteAccess {
// We are also the preferrred scene for receiving files
for fileExtension in ["png", "jpeg", "jpg", "pdf"] {
preferredActivatePredicates.append(NSPredicate(format: "SELF ENDSWITH[c] '.%@'", fileExtension))
}
}
let conditions = UISceneActivationConditions()
conditions.canActivateForTargetContentIdentifierPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: canActivatePredicates)
conditions.prefersToActivateForTargetContentIdentifierPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: preferredActivatePredicates)
scene.activationConditions = conditions
Unfortunately, this does not seem to have an effect. It does not activate the hasWriteAccess
scenes for func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>)
Is there any way to tell what content identifier the system is using when a file share activates an app?
Thank you for your help!
var preferredActivatePredicates = [NSPredicate]()
var canActivatePredicates = [NSPredicate]()
// Any scene *can* be activated at any time
canActivatePredicates.append(NSPredicate(value: true))
if hasWriteAccess {
// We are also the preferrred scene for receiving files
for fileExtension in ["png", "jpeg", "jpg", "pdf"] {
preferredActivatePredicates.append(NSPredicate(format: "SELF ENDSWITH[c] '.%@'", fileExtension))
}
}
Seems like you are evaluating your predicate condition within the scope of your app.
Unfortunately, the system doesn't package up code within your running application and ship it out to other parts of the system, so UIKit must be able to evaluate your predicate’s conditions outside the scope of your app, so don’t include conditions that require dynamic evaluation.
For example, don’t include key paths in your predicate and don’t create predicates that evaluate conditions using selectors or blocks. Also, block-based predicates aren't allowed.
Next, regular expression-based predicates aren't allowed because they could introduce an indeterminate amount of time during the evaluation of your scene predicates.
And finally, the only keypath your NSPredicate can reference is Self
. Which is to say, you're not going to set your scene activation requirement predicates on something along the lines of the length of the string or your target content identifier. We want you to put real content that you could actually use in your model there.
Here's a good example of a predicate that doesn't need to be evaluated based on the scope of your app :
let crustyPredicate = NSPredicate(format: "self == 'http://clowntown.example.com/clown/
Crusty'")
let conditions = scene.activationConditions
conditions.prefersToActivateForTargetContentIdentifierPredicate = crustyPredicate
conditions.canActivateForTargetContentIdentifierPredicate = crustyPredicate
I would suggest you review Targeting Content with Multiple Windows WWDC session, it goes over how to identify which scene the system should open from a notification, a shortcut item, and other user activities.