Not able to select multiple files using UIDocumentPickerViewController - ios

I'm trying to import/pick multiple files at once from files app using UIDocumentPickerViewController. Tried setting allowsMultipleSelection = true but still there is no "Select" option while picker is presented.
Code snippet :
UIDocumentPickerViewController *dvc = [[UIDocumentPickerViewController alloc]initWithDocumentTypes:arrContents inMode:UIDocumentPickerModeImport];
dvc.delegate = self;
dvc.allowsMultipleSelection = true;
[self presentViewController:dvc animated:true completion:nil];
Screenshot :

This is a bug Apple needs to fix. You can use this workaround. If you set animated: to YES, it will only work the first time you show the document picker.
Objective-C:
[self presentViewController:dvc animated:NO completion:^{
if (#available(iOS 11.0, *)) {
dvc.allowsMultipleSelection = YES;
}
}];
Swift 4:
self.present(dvc, animated: false) {
if #available(iOS 11.0, *) {
dvc.allowsMultipleSelection = true;
}
}

Related

How do I enable multiple files selection while picking file using UIDocumentPickerViewController?

I'm trying to pick file from Files App using UIDocumentPickerViewController but I can't see Select button for multiple selection in picker. Why this is happening? am i doing anything wrong? Can anyone help?
Code snippet :
NSArray *arrContents = #[#"public.content",#"public.item",#"public.composite-content",#"public.data",#"public.database",#"public.calendar-event",#"public.message",#"public.presentation",#"public.contact",#"public.archive",#"public.disk-image",#"public.text",#"public.plain-text",#"public.utf8-plain-text",#"public.utf16-external-plain-​text",#"public.utf16-plain-text",#"com.apple.traditional-mac-​plain-text",#"public.rtf"];
UIDocumentPickerViewController *dvc = [[UIDocumentPickerViewController
alloc]initWithDocumentTypes:arrContents inMode:UIDocumentPickerModeImport];
dvc.delegate = self;
[self presentViewController:dvc animated:true completion:nil];
set dvc.allowsMultipleSelection = true; after initialising UIDocumentPickerViewController.

SFSafariViewController blank in iOS 11/Xcode 9.0

I have a SFSafariViewController opening at the click of a button inside a UIActionSheet. It has been working fine and is still working fine on all the versions of iOS except iOS 11. Is there something they have changed regarding the SFSafariViewController in iOS 11 or in Xcode 9.0 that might have caused this issue?
UPDATE - So it seems like its Xcode 9.0 that is causing this issue. I have tried running it on different iOS versions and all of them seem to be giving this issue. It used to work fine when I ran it using Xcode 8.3.3, something I don't have anymore :(
Here's the code -
- (void)presentWebView:(NSString *)url {
url = [url stringByReplacingOccurrencesOfString:#" " withString:#"+"];
url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *URL = [NSURL URLWithString:url];
if (URL) {
if ([SFSafariViewController class] != nil) {
SFSafariViewController *sfvc = [[SFSafariViewController alloc] initWithURL:URL];
sfvc.delegate = self;
[self.tabBarController presentViewController:sfvc animated:YES completion:nil];
} else {
if (![[UIApplication sharedApplication] openURL:URL]) {
NSLog(#"%#%#",#"Failed to open url:",[url description]);
}
}
} else {
// will have a nice alert displaying soon.
}
}
I've managed to fix this in my code. I hope this helps anyone else with a similar problem.
I had the exact same problem as described here. I tried everything above and unfortunately nothing worked.
In my app there were different windows. The fix was to ensure the window that would show SFSafariViewController was 'key' before presenting it. For example:
class MyViewController: UIViewcontroller {
func showSafariViewController() {
// imagine we have 2 windows, one for 'normal' content (key window) and one for 'other' content. lets say we're showing the 'other' content window, and have hidden the 'normal' window. you can see the 'other' content window in the app, but it won't be the key window!
let window = // get the 'other' content window
// make sure we make it the key window before presenting safari
window.makeKey()
// now present safari and celebrate victory by triumphantly slurping on your hot black coffee
let mySafariViewController = SFSafariViewController(...)
self.present(mySafariViewController ...)
}
}
I suspect Apple are searching for a SFSafariViewController instance in the window UIApplication.shared.keyWindow. Perhaps they're adding a child view from somewhere else. In the documentation it states The user's activity and interaction with SFSafariViewController are not visible to your app, so perhaps it's the bug is something related to an added level of security https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller
I have tried to do it using delay and make view of controller loading.Both are working for me.
Method 1. Using delay.
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
let controller = SFSafariViewController(url: url)
controller.modalPresentationStyle = .overFullScreen
self.present(controller, animated: true, completion: nil)
controller.delegate = self
}
Method 2. Loading view.
let controller = SFSafariViewController(url: url)
let _ = controller.view
controller.modalPresentationStyle = .overFullScreen
self.present(controller, animated: true, completion: nil)
controller.delegate = self
Very similar to https://openradar.appspot.com/29108332
To fix it, you can disable the lazy loading of the view:
SFSafariViewController *viewController = [[SFSafariViewController alloc] init...];
(void)viewController.view;
...
[controller presentViewController:viewController animated:YES completion:nil];
Update
Turns out the old answer didn't work, it just worked since I put breakpoints. If I added a thread sleep seems it worked in XCode9, but that's not the best solution. Anyone have another better solution?
SFSafariViewController *sfcontroller = [[SFSafariViewController alloc] initWithURL:url];
if (#available(iOS 11.0, *)) {
[NSThread sleepForTimeInterval:0.5f];
}
sfcontroller.delegate = self;
[controller presentViewController:sfcontroller animated:NO completion:nil];
Old Answer
I have the same issue as genaks and tinkered around with SFViewController.
Seems like this code works for me
SFSafariViewController *sfcontroller = [[SFSafariViewController alloc] initWithURL:url];
if (#available(iOS 11.0, *)) {
SFSafariViewControllerConfiguration *config = [[SFSafariViewControllerConfiguration alloc] init];
config.barCollapsingEnabled = NO;
sfcontroller = [[SFSafariViewController alloc] initWithURL:url configuration: config];
} else {
// Fallback on earlier versions
}
sfcontroller.delegate = self;
[controller presentViewController:sfcontroller animated:YES completion:nil];
In ios 11, they introduce SFSafariViewControllerConfiguration, and by default the barCollapsingEnabled is true and it seems the one that causing my blank SafariView. Hope this solves yours too
We had this issue: our URL was https://our-side.com/index.html (an Angular site that would redirect to the /account route). When we removed the index.html, the SFSafariViewController loaded correctly!
The only thing that has worked so far for me is to make the SafariViewController the rootviewcontroller in the following manner -
((XYZAppDelegate *)[UIApplication sharedApplication].delegate).window.rootViewController = self.svc;
[((XYZAppDelegate *)[UIApplication sharedApplication].delegate).window makeKeyAndVisible];

UIDocumentInteractionController stopped working iOS 8

I have a PDF file saved in the document directory. The path to the file is stored in a NSString property 'self.URL'.
Here is my code to present the activity items:
-(void)presentDocumentInteractionController{
self.docController = [UIDocumentInteractionController interactionControllerWithURL:self.URL];
self.docController.delegate = self;
[_docController setUTI:#"com.adobe.pdf"];
[_docController presentOptionsMenuFromBarButtonItem:self.activityBarButton animated:YES];
}
Before iOS 8 this code worked fine. The user was presented with a list of items such as print, copy and email to choose from. After upgrading to iOS 8 /XCode 6, I'm getting this runtime error (it doesnt crash the app):
Unknown activity items supplied: (
"<UITextViewPrintFormatter: 0x7f908ba53ca0>"
)
How can I solve this problem?
I have the same problem and have switched to using UIActivityViewController. However this makes the apps capable of opening the PDF no longer show up, so maybe that's not what you want.
Minimal Solution:
If you want to do minimal work, you don't even need to read your PDF into NSData, use a NSURL as activity item and iOS seems to know what to do:
- (void)share:(id)sender
{
UIActivityViewController *activity =
[[UIActivityViewController alloc] initWithActivityItems:#[self.URL]
applicationActivities:nil];
if ([activity respondsToSelector:#selector(popoverPresentationController)]) {
activity.popoverPresentationController.barButtonItem = <# BAR BUTTON ITEM #>;
}
[self presentViewController:activity animated:YES completion:NULL];
}
Original Answer:
Make your view controller adhere to the UIActivityItemSource protocol, then you can do:
- (void)share:(id)sender
{
self.pdfData = [NSData dataWithContentsOfURL:self.URL];
UIActivityViewController *activity = [[UIActivityViewController alloc] initWithActivityItems:#[self] applicationActivities:nil];
if ([activity respondsToSelector:#selector(popoverPresentationController)]) {
activity.popoverPresentationController.barButtonItem = <# BAR BUTTON ITEM #>;
}
[self presentViewController:activity animated:YES completion:NULL];
}
Adhering to the protocol if you have a PDF file is relatively simple. You can of course optimize and return smaller NSData and even a preview image, but minimally do this:
- (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
{
return _pdfData;
}
- (id)activityViewController:(UIActivityViewController *)activityViewController
itemForActivityType:(NSString *)activityType
{
return _pdfData;
}
- (NSString *)activityViewController:(UIActivityViewController *)activityViewController
subjectForActivityType:(NSString *)activityType
{
return self.title;
}
- (NSString *)activityViewController:(UIActivityViewController *)activityViewController
dataTypeIdentifierForActivityType:(NSString *)activityType
{
return #"com.adobe.pdf";
}
Use
- (BOOL)presentOpenInMenuFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated;
Instead of
- (BOOL)presentOptionsMenuFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated;
This solved the problem for me:
ObjC:
dispatch_async(dispatch_get_main_queue(), ^() {
[_docController presentOptionsMenuFromRect:button.bounds inView:button animated:YES];
});
Swift:
if let docController = UIDocumentInteractionController(URL: url) {
dispatch_async(dispatch_get_main_queue()) {
docController.presentPreviewAnimated(true)
}
} else {
// handle nil docController
}
I don't use swift so this code might not work.

open appstore as model view opens blank page ios

I am tring to open appstore page as model view inside application using following code
[NSDictionary dictionaryWithObject:#"APPID" forKey:SKStoreProductParameterITunesItemIdentifier];
SKStoreProductViewController *productViewController = [[SKStoreProductViewController alloc] init];
[self presentViewController:productViewController animated:YES completion:nil];
but when appstore is open inside application, it is opening as blank page.
Please refer screenshoot attached
I dont understand why appstore page of my app is not opening. I am passing APPID in above code.
Is there any other way to rate application without closing app ?
basically, something like this could help on you, after you linked the StoreKit.framework to your project. please note, it may not be working on simulator; on real device it works well.
.h
#interface UIYourViewController : UIViewController <SKStoreProductViewControllerDelegate> { }
.m
- (void)myOwnCustomMethod {
SKStoreProductViewController *_controller = [[SKStoreProductViewController alloc] init];
[_controller setDelegate:self];
[_controller loadProductWithParameters:[NSDictionary dictionaryWithObjectsAndKeys:#"364709193", SKStoreProductParameterITunesItemIdentifier, nil] completionBlock:^(BOOL result, NSError *error) {
if (result) {
[self.navigationController presentViewController:_controller animated:TRUE completion:nil];
} else {
// you can handle the error here, if you'd like to.
}
}];
}
#pragma mark - <SKStoreProductViewControllerDelegate>
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
[self dismissViewControllerAnimated:TRUE completion:nil];
}
In Swift 3,
import StoreKit
class DetailViewController: UIViewController {
#IBAction func onEditButton(_ sender: UIBarButtonItem) {
let vc = SKStoreProductViewController()
vc.delegate = self
present(vc, animated: true, completion: nil)
vc.loadProduct(withParameters: [SKStoreProductParameterITunesItemIdentifier: 351091731]) { (success, error) in
if !success {
print("\(error)")
}
}
}
}
extension DetailViewController: SKStoreProductViewControllerDelegate {
func productViewControllerDidFinish(_ viewController: SKStoreProductViewController) {
viewController.dismiss(animated: true, completion: nil)
}
}
Make sure SKStoreProductParameterITunesItemIdentifier's value is Number, as stated in its head file, though String value is currently OK.

UIImagePickerController not full screen

Since the iOS7 upgrade, I have a weird behaviour of the UIImagePickerController. In this application I am using the UIImagePickerController with a cameraOverlayView.
In iOS6 I called the UIImagePickerController using the following code:
_picker = [[UIImagePickerController alloc] init];
if ([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear]) {
_picker.sourceType = UIImagePickerControllerSourceTypeCamera;
_picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
_picker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
_picker.showsCameraControls = NO;
_picker.navigationBarHidden = NO;
_picker.toolbarHidden = YES;
_picker.wantsFullScreenLayout = YES;
_overlayViewController = [[OverlayViewController alloc] init];
_overlayViewController.picker = _picker;
_overlayViewController.frameSize = self.frameSize;
_overlayViewController.delegate = self;
_picker.cameraOverlayView = _overlayViewController.view;
}
else {
_picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
_picker.delegate = self;
Where the OverlayViewController is an UIViewController, with a transparent background which draws some custom controls on screen.
But now in iOS 7 the camera is drawn through the statusbar and a black bar appears beneath the live camera view.
I can solve this by applying a CGAffineTransformMakeTranslation to the cameraViewTransform property of the UIImagePickerController, but why is this like this?
In iOS 7, by default UIViewController views take up the entire screen area including the status bar.
wantsFullScreenLayout
is deprecated and ignored. In some cases, this fix works (in the view controller class):
if ([self respondsToSelector:#selector(setEdgesForExtendedLayout:)]) {
[self setEdgesForExtendedLayout:UIRectEdgeNone];
}
In other cases, it's a bit more complicated. It's late here, so see how you go with it. Helpful things to note - in a UIViewController, the following code will give the correct statusbar height on both iOS 6 and iOS 7, should it come to having to align things using CGRect math:
if (UIDeviceOrientationIsLandscape(self.interfaceOrientation)) {
statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.width;
} else {
statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
}
And then don't forget that in Interface Builder, there are the new "iOS 6 delta" adjustments that allow you to design for iOS 7 and then use offsets to correct for iOS 6.
Anyhow, let me know how you go.
My understanding of the issue, based on a few other SO threads and such, is that UIImagePickerController does not do what we'd expect in terms of managing the status bar via [UIViewController -prefersStatusBarHidden].
This means you either have to disable view controller status bar management entirely, via plist, or figure out a way to get UIImagePickerController to do what we want. On the assumption that you're not looking for the former, I can say I've had success in the latter by putting the picker in a wrapper controller that does what I want (but fall back to your previous code if you still need to detect/support iOS6):
#interface PickerContainer : UIViewController
#property ( nonatomic, weak ) UIImagePickerController* picker;
#end
#implementation PickerContainer
- (void) setPicker: (UIImagePickerController*) picker
{
[self addChildViewController: picker];
[picker didMoveToParentViewController: self];
self->_picker = picker;
}
- (void) viewDidLoad
{
[super viewDidLoad];
self.picker.view.frame = self.view.bounds;
[self.view addSubview: self.picker.view];
}
// Will have no effect in ios6 -- see [-init] for that option
- (BOOL) prefersStatusBarHidden { return YES; }
- (id) init
{
if ( ! ( self = [super init] ) ) return nil;
if ( detectThatThisIsIos6() ) self.wantsFullScreenLayout = YES;
return self;
}
#end
This will work for you, scaled camera, you will have a black bar at the bottom but it will get overlayed by tool bar
https://stackoverflow.com/a/15803947

Resources