I have Dropbox installed on my iOS 8.02 iPad.
I want to export files to either Dropbox or iCloud Drive via the UIDocumentPickerViewController.
If I present my controller using mode 'UIDocumentPickerModeMoveToService'
UIDocumentPickerViewController *viewController = [[UIDocumentPickerViewController alloc] initWithURL:self.datasource.myFileUrl inMode:UIDocumentPickerModeMoveToService];
viewController.delegate = self;
[self presentViewController:viewController animated:YES completion:^{}];
I do not get a Locations nav-bar button and so cannot select DropBox as an alternative location...
Whereas is I use mode 'UIDocumentPickerModeExportToService' when creating my controller, I do get the Locations menu item...
According to the Apple docs, there's a subtle difference between the two modes...
UIDocumentPickerModeExportToService The document picker exports a
local file to a destination outside the app’s sandbox.
Available in iOS 8.0 and later.
UIDocumentPickerModeMoveToService The document picker moves a local
file outside the app’s sandbox and provides access to it as an
external file.
Available in iOS 8.0 and later.
Which to me, doesn't signal that Locations will be restricted depending on which mode I select.
Is this a bug, or am I doing something wrong here?
This appears to have been a bug as it is now working correctly in 8.1
Related
I have an iPad app in which I'm starting to support multiple windows / scenes. I have one main window type, let's say MainScene, and at least one secondary window type for opening specific types of content, say DetailScene.
I have not declared my scene types in Info.plist. I have implemented application:configurationForConnectingSceneSession:options: like this:
-(UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options
{
NSUserActivity *activity = options.userActivities.anyObject;
NSString *activityType = activity.activityType;
if ([activityType isEqualToString:#"detailType"])
return [DetailSceneDelegate makeSceneConfiguration];
return [MainSceneDelegate makeSceneConfiguration];
}
Say I perform these steps:
Launch app for the first time. I get a call to configurationForConnectingSceneSession, and the activity type is nil so it returns a MainScene.
Open a new window for some piece of content. That uses the detail scene activity type, so configurationForConnectingSceneSession returns a DetailScene. Creating the new scene looks like this:
NSUserActivity *activity = [[NSUserActivity alloc] initWithActivityType:#"detailType"];
activity.userInfo = #{#"content_id": #(contentRowId)};
[[UIApplication sharedApplication] requestSceneSessionActivation:nil userActivity:activity options:nil errorHandler:nil];
Suspend the app and open the app switcher. Discard (by flicking up) first the main window and then the detail window. The app is now killed.
Relaunch the app.
At this point I do not get a call to configurationForConnectingSceneSession. I get the detail scene back, restored from its user activity, with calls straight to DetailSceneDelegate.
My question: how do I control what scene gets restored in this situation? I want my main scene to come back.
Messages and Mail and Notes all do this. If you open Messages and drag a conversation out into a new window, you get a window for that conversation with a Done button in the corner that will dismiss the window. If you perform my steps above with Messages, you will relaunch to the full Messages view. Are they converting the detail view to a main view on the fly? Or is there a way to tell the system that the detail scene is secondary and should not be restored first, or that I should get asked what I want to restore via configurationForConnectingSceneSession? Or something else?
I cross-posted this to the Apple Developer forums and got an answer from a Framework Engineer. The answer is UISceneActivationConditions, set as a property on UIScene. Set the canActivateForTargetContentIdentifierPredicate to always return NO:
scene.activationConditions.canActivateForTargetContentIdentifierPredicate = [NSPredicate predicateWithValue:NO];
I do this in my implementation of scene:willConnectToSession:options: in my UIWindowSceneDelegate implementation.
As of current writing, on Xcode 13.2 and iOS 15.2 simulator, it works if the second launch (step 4 above) is via tapping the app icon, but not when it's via building and running in Xcode. I may file a feedback on this.
For my iOS app built with unity engine, I have a use case where I would want to direct the user to settings page from within the app itself. I am using objectiveC to create a custom plugin for iOS that directs user to settings page. But it backgrounds the app and brings up the settings page. I would like to be able to achieve this from within the app itself if its possible to show settings in some kind of subview popup in the app? I have seen this somewhere for example where the app brings up a mail subview or a google map subview inside the app itself but not sure if its possible for doing something similar with iOS native settings page?
Currently i am using openURL to simply direct user to settings URL page but I would like this to be embedded in some subview from within the app itself
NSURL *url = [NSURL URLWithString:#"prefs:root=NOTIFICATIONS_ID"];
[[UIApplication sharedApplication] openURL:url];
Any ideas?
It's not possible to show a portion of the Settings app in your own app like you can do with mail or maps. However, you can build your own UI within your app to edit settings.
I wrote a tweak for Cydia, it adds an icon to the status bar.
It works fine on the home screen and when SpringBoard is launched, also, if an app is already launched then it works fine,
however, if an app (such as Facebook or Twitter) is closed (completely) and the icon is showing, when launching the app, it will cause the icon to disappear.
The icon is displayed using libStatusBar using this code:
if(icon) // if icon needs to be removed
{
[icon release];
icon = nil;
}
...
// add the icon to the status bar
icon = [[%c(LSStatusBarItem) alloc] initWithIdentifier:[NSString stringWithFormat:#"muteIconLablabla"] alignment:StatusBarAlignmentRight];
icon.imageName = [NSString stringWithFormat:#"Mute"];
I also tried using the methods suggested in libStatusBar README file
[[UIApplication sharedApplication] addStatusBarImageNamed:#"ON_Mute"]; // and removeStatusBarImageNamed:...
I tried overriding -(id)init and updating the icon there, but the same result.
The code shown above is being called from a static void function. this function is being called several times, for example from -(void)applicationDidFinishLaunching:(id)application
under %hook SpringBoard and -(void)ringerChanged:(int)changed
All inside Tweak.xm.
The problem happens in iOS7 as well.
It's been a while since I've used libstatusbar, but if you are absolutely sure the LSStatusBarItem is not being released, it's possible it's being hidden by Springboard or another app. Consider setting icon.visible = YES explicitly. You also might want to consider setting timeHidden on LSStatusBarServer to NO explicitly by calling [item setHidesTime:NO].
Additionally, if you're not making any changes to the icon, set icon.manualUpdate = NO.
References:
Libstatusbar on the iPhoneDevWiki
LSStatusBarItem.mm source
I am writing an iPad kiosk-type application that allows a visitor to record a video using the front facing camera and view existing videos in the Camera Roll that are targeting an External monitor. I am just learning XCode, and working in Xcode 4.4.1 targeting iOS 5. It seems like a lot has changed recently and this is making it much harder to learn so I am trying to keep things as simple as possible, that's why I am using UIImagePicker.
Everything is working as I wish, with one exception – I am not able to toggle between the external display and the iPad as I want. When the user records a video, it is full screen on the iPad. That's fine, however after they stop recording, the video is immediately sent to the external display for approval and a placeholder image is left in the UIPopover. What I would rather see/do is either keep the video preview full screen on the iPad, or target the video to the UIPopover.
The reason is that the external display is not easily viewable from where the user is accessing the iPad. Therefore, they are being asked to approve (click Use) on something they can't really see. It would be much better to keep it on the iPad. The code below is what I have used to allow recording.
Everything else works great, I want the user to select videos from the Library and display on the External monitor, and since that's the default behavior it works fine.
The closest answer I could find so far is this: UIImagePickerController in an existing UIPopoverController
Is there a simple way to disable the external display or keep the video preview from being sent?
- (IBAction)useCameraRoll:(id)sender
{
if([self.popoverController isPopoverVisible]) {
[self.popoverController dismissPopoverAnimated:YES];
} else {
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum])
{
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
imagePicker.mediaTypes = [NSArray arrayWithObjects:(NSString *) kUTTypeMovie, nil];
imagePicker.allowsEditing = NO;
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:imagePicker];
//self.popoverController = [[UIPopoverController alloc] setContentViewController:animated];
self.popoverController.delegate = self;
[self.popoverController
presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
newMedia = NO;
}
}
}
Coincidentally, I have been working on a similar kiosk app with an iPad. In my case it utilizes some Augmented Reality to show relevant content on the external display. I use the iPad screen as a configuration panel for the augmented reality experience.
Best way, that I found, to approach this, would be to use separate windows with the two UIScreens for each of the displays. This enables you to craft the experience properly. I am not sure if you are using this approach already, but if you aren't, then this is the way to go.
To get started you can read the ExternalDisplay code sample. From the excerpt:
From the ExternalDisplay sample code in the iOS Developer Library:
To display content on an external display, do the following:
Use the screens class method of the UIScreen class to determine if an external display is available.
If an external screen is available, get the screen object and look at the values in its availableModes property. This property contains
the configurations supported by the screen.
Select the UIScreenMode object corresponding to the desired resolution and assign it to the currentMode property of the screen
object.
Create a new window object (UIWindow) to display your content.
Assign the screen object to the screen property of your new window.
Configure the window (by adding views or setting up your OpenGL ES rendering context).
Show the window.
Also, the UIScreen documentation is quitehelpful.
I implemented a UIDocumentInteractionController to send files to other apps. The file is a .txt file.
Here's the code:
UIDocumentInteractionController *interactionController = [[UIDocumentInteractionController alloc] init];
[interactionController setURL:[NSURL fileURLWithPath:filePath]];
[interactionController setUTI:#"public.text"];
[interactionController setDelegate:self];
[interactionController presentOpenInMenuFromBarButtonItem:actionBarButtonItem animated:YES];
The menu opens fine, showing apps like Pages, Dropbox, etc. as I expect. But when I tap one of them, the Open In menu dismisses and no action is performed (the file is not sent and the target application never opens.
I tried implementing the delegate methods documentInteractionController:canPerformAction: and documentInteractionController:performAction: for triggering copy: and print: calls using the options menu (as opposed to the open in menu) and that pulled up a menu with only Pages listed, but that still did not work.
How might this be resolved?
I found the answer, and it's memory management. I create the UIDocumentInteractionController and then present it, but I don't have it as an instance variable. ARC deallocates it before it has the opportunity to do anything. This includes sending the document to the external app.
This bug didn't appear on the iPhone, but on the iPad it gives an error because the popover architecture works a bit differently and it ends up trying to draw it when it's deallocated. That's what alerted me to the bug.
This bug also appears on iPhone/iPod. Just set:
#property (nonatomic, retain) UIDocumentInteractionController *docController;
and it will be retain and the document passed to the new application.
it's enough to add the following code:
[interactionController retain];