UIImagePicker Controller doesn't request permission even with plist entry - ios

I am having trouble with UIImagePickerController. I want to be able to open the photo library and select an image, when I do I get the following error
[discovery] errors encountered while discovering extensions: Error Domain=PlugInKit Code=13 "query cancelled" UserInfo={NSLocalizedDescription=query cancelled}`
I assumed this was probably a permissions error since I mistakenly hadn't added a row in my plist for photo access so I added the entry for photo library access:
Privacy - Photo library Usage Description with the type string and value set to photo use
and still I get no prompt for permission to access photos when I try and access them.
To minimise anything else causing problems I have made a new project it simply has a single view controller and the above entry in the plist, below shows the only code in this class
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate
{
var mImagePicker:UIImagePickerController?
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func tapped(_ sender: Any)
{
// Pick an image from the photo library
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary)
{
mImagePicker = UIImagePickerController()
mImagePicker!.delegate = self
mImagePicker!.sourceType = .photoLibrary;
mImagePicker!.allowsEditing = false
self.present(mImagePicker!, animated: true, completion: nil)
}
}
}
when I tap the button I see no prompt for permission, the photo library simply appears and when I select a photo I get the error shown above? is there something I'm missing here?
Im running iOS 12 on an iPhone X and Xcode 10.0 on the latest version of the Mojave beta

You don't actually need permission if you're just accessing photos using UIImagePickerController from iOS 11. Permission is required when you use AVFoundation or Photos framework.
In my experience, iOS logs those errors that we can ignore sometimes, and I think you can ignore the error messages this time.

Related

ReplayKit Broadcast upload extension - Service not found

I'm working on an IOS swift application that will allow the user to record the entire screen, any app and even the home screen.
In order to do that, I added a Broadcast Upload Extension to my app.
First I used the RPSystemBroadcastPickerView class in order to add a record button to my view that allow the user to open the record popup and select to which app he wants to broadcast the screen flow. And it's working fine :
But I would like to avoid this step and directly open the popup when the app launch.
So I wrote the following code to do that :
RPBroadcastActivityViewController.load(withPreferredExtension: "ch.jroueche.RecordApp.TestScreen", handler: {broadcastAVC,error in
guard error == nil else {
print("Cannot load Broadcast Activity View Controller.")
return
}
if let broadcastAVC = broadcastAVC {
broadcastAVC.delegate = self
self.present(broadcastAVC, animated: true, completion: {
// broadcastactivityviewcontroller will perform the callback when the broadcast starts (or fails)
print("I've START")
})
}
})
Unlikeenter code here the RPSystemBroadcastPickerView solution, I'm getting the following error :
The preferred broadcast service could not be found.
My issue is similar to the following post :
App not showing up as a broadcast service in RPBroadcastActivityViewController
I also added the extension and the preferred extension identifier is correct.
Why would it be possible using the RPSystemBroadcastPickerView and not programmatically using RPBroadcastActivityViewControllerclass. That does not make sense for me.
Does someone have an idea of what could be the issue and how could I fix it ? Or a workaround in order to do this screen record.
Thanks in advance
It appears that RPBroadcastActivityViewController shows ONLY Broadcast Setup UI Extension, while RPSystemBroadcastPickerView shows ONLY Broadcast Upload Extension. But I have no idea why, as both of them are stated to show list of available providers/services.
It would be very helpful if someone could bring more details on the topic.

iOS 13 How to use UIDocumentPickerViewController with App Group?

I have implemented an AppGroup in my app in preparation for sharing data with another app. I have successfully moved files to that App Group from the default app documents directory.
FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.xxx.mydata")! as NSURL
Now I would like to select from the files in that container, using UIDocumentPickerViewController. In iOS 13,I should be able to set which directory the document picker starts in. My documentPicker looks like this:
#IBAction func fileAction(_ sender: UIButton)
{
// open a document picker, select a file
let importFileMenu = UIDocumentPickerViewController(documentTypes: ["public.data"],
in: UIDocumentPickerMode.import)
importFileMenu.delegate = self
if #available(iOS 13.0, *) {
print("File iOS 13+")
importFileMenu.directoryURL = FileManager.default.containerURL(
forSecurityApplicationGroupIdentifier: "group.com.xxx.mydata")!
} else {
// Fallback on earlier versions
print("File iOS <=12")
}
importFileMenu.modalPresentationStyle = .formSheet
self.present(importFileMenu, animated: true, completion: nil)
}
When I run the app, it acts as it did before iOS13, opening in the default app documents directory, and the App Group is not shown as a possibility for selection. The print statement shows "File iOS 13+".
Am I missing permissions to read from that container, or is there something else that I've missed?
Thanks!
No, sorry, it can't be done. Apple says that selecting from an AppGroup is not what UIDocumentPickerViewController is supposed to do. I spent one of my "Apple Developer Tech Support" uses on this, and that was their answer. I gave up on that for now, and went a different direction. You should be able to build your own list of files in the AppGroup and select them, just not by using UIDocumentPickerViewController.

Twitterkit present a new viewcontroller instead present on a target viewController

Im using TwiterKit 3.0 framwork. And im using Deeplink to share a tweet for my application. But the problem is its presenting a new viewController and shows the twitter dialogue box. But my requirement is need to share like in Photos app sharing screen.
if let deepLinkurl = branchObject.getShortUrl(with: shareLinkProperties) {
let composer = TWTRComposer()
composer.setURL(URL(string: deepLinkURL))
composer.show(from: self) { result in
if (result == TWTRComposerResult.cancelled) {
print("Tweet composition cancelled")
}
}
If i run above code I get like this
But I need something like this.
You can use Branch's showShareSheet() method for sharing Branch links to other apps.
Here is how the link is shared when using the shareSheet and selecting Twitter from the list of the Apps.
You can check out the documentation here

Loading Contacts Crashing iOS 10 Swift [duplicate]

This question already has answers here:
What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean?
(16 answers)
Closed 6 years ago.
I am trying to access and load all contacts on iOS 10; however, my app crashes every time the controller loads. I just converted my project from Swift 2 to Swift 2.3 (it was working on Swift 2). I have also added the Privacy Usage for Contacts in my info.plist, but that did not fix the issue. Here is my code:
I found this from a tutorial online to request for access :
func checkAccessStatus(completionHandler: (accessGranted: Bool) -> Void) {
let authorizationStatus = CNContactStore.authorizationStatusForEntityType(CNEntityType.Contacts)
switch authorizationStatus {
case .Authorized:
completionHandler(accessGranted: true)
case .Denied, .NotDetermined:
self.accessStore.requestAccessForEntityType(CNEntityType.Contacts, completionHandler: { (access, accessError) -> Void in
if access {
completionHandler(accessGranted: access)
} else {
print("access denied")
print(accessError)
}
})
default:
completionHandler(accessGranted: false)
}
}
I keep getting this error:
"Optional(Error Domain=CNErrorDomain Code=100 "Access Denied" UserInfo={NSLocalizedDescription=Access Denied, NSLocalizedFailureReason=This application has not been granted permission to access Contacts.})"
The code above is a snipper from my controller where the error is happening. I am attempting to request access but it keeps failing. Are there additional steps I need to do to receive access to the contacts? I am not getting a popup box asking for permission when I load the page (even though I added the privacy bit in the info.plist for contacts usage). I have also checked the privacy settings & looked to see if I had disabled the app's access to contacts; however, it is not showing. I appreciate any help, thank you!
Update: I found this question, which seems to be a similar problem (though it is iOS 9) here. How do I delete my info.plist and make a new one?
Move checkAccessStatus to your Contact Controller and try this method again?

How to test if "Allow Full Access" permission is granted from containing app?

I'm working on a keyboard extension project. At some points of the application code I need to test if the user have granted the "Allow Full Access" permission for the keyboard extension. The deal is that I need to do those tests from the application side, and based on this let the user to access keyboard settings or alert him in case the permission wasn't granted.
The problem is that the methods that provided here like:
func isOpenAccessGranted() -> Bool {
return UIPasteboard.generalPasteboard().isKindOfClass(UIPasteboard)
}
or:
func isOpenAccessGranted() -> Bool {
let fm = NSFileManager.defaultManager()
let containerPath = fm.containerURLForSecurityApplicationGroupIdentifier(
"group.com.example")?.path
var error: NSError?
fm.contentsOfDirectoryAtPath(containerPath!, error: &error)
if (error != nil) {
NSLog("Full Access: Off")
return false
}
NSLog("Full Access: On");
return true
}
Working only from the keyboard side, as the keyboard is the only one that is affected from this permission. From the containing app side both of those methods always return true.
Does someone knows a reliable way to test this from the application side?
Consider using NSUSerdefaults in your app and keyboard. In order for an extension and app to be able to share the same NSUserdefaults, you can simply turn on App Groups. Select your main app target under your project in the project navigator and go to capabilities and enable App Groups by toggling it to on, adding your Developer profile and fixing the possibly arising issues.
Now create a new container. According to the help, it must start with “group.”, so give it a name like “group.com.mycompany.myapp”. Select your Today Extension target and repeat this process of switching on app groups. Don’t create a new one, rather select this newly created group to signify that the Today Extension is a part of the group.
This will now allow you to share the same NSUserdefaults as your container app.
All you have to do now is use the code you provided and add the saving method to the NSUserdefaults like so:
func isOpenAccessGranted() -> Bool {
let defaults = NSUserDefaults.standardUserDefaults()
let fm = NSFileManager.defaultManager()
let containerPath = fm.containerURLForSecurityApplicationGroupIdentifier(
"group.com.example")?.path
var error: NSError?
fm.contentsOfDirectoryAtPath(containerPath!, error: &error)
if (error != nil) {
NSLog("Full Access: Off")
defaults.setBool(false, forKey: "hasFullAccess")
return false
}
NSLog("Full Access: On");
defaults.setBool(true, forKey: "hasFullAccess")
return true
}
Do this in your keyboard extension. And then in your parent app, simply retrieve them and act upon their value.
let hasFullAccess : Bool = NSUserDefaults.standardUserDefaults().boolForKey("hasFullAccess")
if hasFullAccess{
//User granted full access
}
else{
//User didn't grant full access
}
If the user didn't grant full access the show an alert, else code away!
EDIT:
After contacting Apple's Technical Developer support they told me that this is not possible to achieve in any supported way as of right now. Their response is below:
Our engineers have reviewed your request and have concluded that there
is no supported way to achieve the desired functionality given the
currently shipping system configurations.
If you would like for Apple to consider adding support for such
features in the future, please submit an enhancement request via the
Bug Reporter tool at https://developer.apple.com/bug-reporting/.
Hope that helps, Julian
You can easily test whether the "Allow Full Access" permission is granted on iOS 11 and later.
To get the "Allow Full Access" permission, first subclass the
UIInputViewController class.
Add the code. The code returns a bool value.
Objective-C
[self hasFullAccess];
Swift
self.hasFullAccess
https://developer.apple.com/documentation/uikit/uiinputviewcontroller/2875763-hasfullaccess?changes=_2
Objective-C
[UIInputViewController new].hasFullAccess;

Resources