UIActivityViewControllerCompletionWithItemsHandler having error with new update swift - swift

I was working on a basic app a few weeks ago and everything was working fine but now I am having an issue with UIActivityViewControllerCompletionWithItemsHandler
I am new to swift so I am having trouble. I am getting a red line ctivityViewController.completionWithItemsHandler =
Not sure how I am supposed to type it so the image can save. Any help is appreciated!
Here is my code:
#IBAction func shareMeme(_ sender: AnyObject) {
let img: UIImage = generateMemedImage()
let shareItems:Array = [img]
let activityViewController : UIActivityViewController = UIActivityViewController(activityItems: shareItems, applicationActivities: nil)
self.save()
print("Saved")
activityViewController.completionWithItemsHandler = {(activityType, completed:Bool, returnedItems:[AnyObject]?, error: NSError?) in
self.save()
print("Saved")
}
self.present(activityViewController, animated: true, completion: nil)
}

The API changed in Swift 3. Your code needs to be:
activityViewController.completionWithItemsHandler = { (activityType: UIActivityType?, completed: Bool, returnedItems: [Any]?, error: Error?) -> Void in
if completed == true {
self.save()
print("Saved")
}
}
Many, many APIs have changed in Swift 3. Whenever you get an error like this, check the API documentation to see the proper method name and arguments (and their types).

Related

I can't get video selected from gallery swift

My code is here
#IBAction func openVideo(_ sender: Any) {
//selectVideo(delegate: self, sourceType: .savedPhotosAlbum)
let mediaUI = UIImagePickerController()
mediaUI.sourceType = .savedPhotosAlbum
mediaUI.mediaTypes = [kUTTypeMovie as String]
mediaUI.allowsEditing = true
mediaUI.delegate = self
self.present(mediaUI, animated: true, completion: nil)
}
At this part I select video.
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func processVideo(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]){
let url = info[UIImagePickerController.InfoKey.mediaURL] as! URL
print("hey")
self.dismiss(animated: true) {
let player = AVPlayer(url: url)
let vcPlayer = AVPlayerViewController()
vcPlayer.player = player
self.present(vcPlayer, animated: true, completion: nil)
}
}
}
What am I doing wrong?
I can't get any print in processVideo function. I get this error after selecting the video from gallery.
"Error returned from daemon: Error Domain=com.apple.accounts Code=7 "(null)""
You need to set for settings like this or in plist.
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized: // The user has previously granted access to the camera.
self.setupCaptureSession()
case .notDetermined: // The user has not yet been asked for camera access.
AVCaptureDevice.requestAccess(for: .video) { granted in
if granted {
self.setupCaptureSession()
}
}
case .denied: // The user has previously denied access.
return
case .restricted: // The user can't grant access due to restrictions.
return
}
Documentation
Solved problem by changing name of processvideo func to imagePickerController. It seems like name is very important at delegate functions. I didn't notice that.
Tip for creating this delegate function write didfinish and you will get prefer function named imagePickerController, use it.

FirebaseUI not showing any input fields or buttons

I want to implement FirebaseUIin my project, but the login page is not showing any input fields or buttons:
Code for showing FUIAuth:
#IBAction func logInButtonTapped(_ sender: Any) {
let authUI = FUIAuth.defaultAuthUI()
guard authUI != nil else {
//Log error
return
}
authUI?.delegate = self
authUI?.providers = [FUIEmailAuth]()
let authViewController = authUI!.authViewController()
present(authViewController, animated: true, completion: nil)
}
}
extension LogInViewController: FUIAuthDelegate {
func authUI(_ authUI: FUIAuth, didSignInWith authDataResult: AuthDataResult?, error: Error?) {
if error != nil {
return
}
performSegue(withIdentifier: "ToHomeVCSegue", sender: self)
}
}
I have tried lots of different options in the podfile:
pod 'Firebase/Core'
pod 'Firebase/Auth'
pod 'Firebase/Database'
pod 'FirebaseUI'
pod 'FirebaseUI/Email'
I just ran into this same issue and it seems that all of the examples out there are missing some aspect of the steps required to make the providers appear. The first answer was correct but didnt give examples. In the code below I am just suing email and Google auth. This code is embedded in a login button pressed event.
let authUI = FUIAuth.defaultAuthUI()
guard authUI != nil else {
print("authUI error")
return
}
authUI?.delegate = self
let providers: [FUIAuthProvider] = [
FUIEmailAuth(),
FUIGoogleAuth()
]
authUI?.providers = providers
let authViewController = authUI!.authViewController()
present(authViewController, animated: true)
Hopefully it's not too late. But the problem looks to be with this line of code here
authUI?.providers = [FUIEmailAuth]()
The '.providers' property requires an array of type FUIAuthProviders.
Your code is basically trying to pass an array of type FUIEmailAuth, which the '.providers' property doesn't understand.
Here's an example of initializing an array of type FUIAuthProviders
let authProviders: [FUIAuthProviders] = []

Game Center match is invalid always

I'm trying to learn how to build a Game-Center based app. its a turn based extremely simple game that just basically logs what button you press and sends it to he other player. I am having a very hard time implementing all the game center features since Apple's documentation has not been updated for Swift. I've been guessing at everything and reading off Objective-C examples and hoping for the best (somehow I've managed to get a few things going, altough I'm not sure if they are correct)
Anyways, I made a new iCloud account for my Simulator and ran the app on my phone and the simulator simultaneously, trying to get them to match up in a game. However I always get a "match request is invalid" error:
EDIT I have registered the app in iTunesConnect, I've implemented leaderboards and tested them and they work (So I assume the iTunesConnect thing is properly working and set-up)
#IBAction func startTapped(_ sender: Any) {
let request = GKMatchRequest()
request.maxPlayers = 2
request.minPlayers = 1
let mmvc = GKMatchmakerViewController(matchRequest: request)
mmvc?.matchmakerDelegate = self
present(mmvc!, animated: true, completion: nil)
}
extension HomeVC: GKGameCenterControllerDelegate
{
func authenticatePlayer()
{
//CALLED ON VIEWDIDAPPEAR
let localPlayer = GKLocalPlayer.localPlayer()
localPlayer.authenticateHandler = {
(view, error) in
if view != nil
{
self.present(view!, animated: true, completion: nil)
} else {
print("AUTHENTICATED!")
print(GKLocalPlayer.localPlayer().isAuthenticated)
}
}
}
func gameCenterViewControllerDidFinish(_ gameCenterViewController: GKGameCenterViewController) {
gameCenterViewController.dismiss(animated: true, completion: nil)
}
}
Here's the matchmaking code. Note I can get the Game Center screen to appear and tell me "how many players" and that its missing a player and gives the choice to invite friends and all that
extension HomeVC: GKMatchmakerViewControllerDelegate {
func matchmakerViewControllerWasCancelled(_ viewController: GKMatchmakerViewController) {
print("match was cancelled")
viewController.dismiss(animated: true, completion: nil)
}
func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFailWithError error: Error) {
print("didFailwithError: \(error.localizedDescription)")
}
func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFind match: GKMatch) {
print("Match found, ID: \(match.description)")
let gameScreenVC = self.storyboard?.instantiateViewController(withIdentifier: "mainGame") as! ViewController
gameScreenVC.providesPresentationContextTransitionStyle = true
gameScreenVC.definesPresentationContext = true
gameScreenVC.modalPresentationStyle = UIModalPresentationStyle.fullScreen
gameScreenVC.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
match.delegate = gameScreenVC
self.present(gameScreenVC, animated: true, completion: nil)
}
}
If anyone is having this issue I fixed it by just replacing the "minelayers and max-layers" with the same amount, so the code now looks like this:
#IBAction func startTapped(_ sender: Any) {
let request = GKMatchRequest()
request.maxPlayers = 2 //min and max should be the same
request.minPlayers = 2 //apparently they need to be the same
let mmvc = GKMatchmakerViewController(matchRequest: request)
mmvc?.matchmakerDelegate = self
present(mmvc!, animated: true, completion: nil)
}
apparently Game Center does not like a min.player count of 1, its invalid. but thats how I got it to stop giving me Invalid Match Request warnings

MFMailComposeViewController disappear immediately under iOS9

Once I present my MFMailComposeViewController it is dismissed with error:
viewServiceDidTerminateWithError: Error Domain=_UIViewServiceInterfaceErrorDomain Code=3 "(null)" UserInfo={Message=Service Connection Interrupted}
What is going on?
VERY IMPORTANT NOTE
It is working very well under iOS8.
i can't help you since you did not post any code, but here is a working copy of a MailComposeController on iOS9, using it in my app without any problem. Important set your class conform to MFMailComposeViewControllerDelegate. Note that sendMail method is related to a button in my project
#IBAction func sendMail(sender: AnyObject) {
let mailComposeViewController = configuredMailComposeViewController()
if MFMailComposeViewController.canSendMail() {
self.presentViewController(mailComposeViewController, animated: true, completion: nil)
} else {
self.showSendMailErrorAlert()
}
}
func configuredMailComposeViewController() -> MFMailComposeViewController {
let mailComposerVC = MFMailComposeViewController()
mailComposerVC.mailComposeDelegate = self
mailComposerVC.setToRecipients(["yourMail#goesHere"])
return mailComposerVC
}
func showSendMailErrorAlert() {
print("There was an error.")
//In case of error with email account on device, you should implement an alert here
}
func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
controller.dismissViewControllerAnimated(true, completion: nil)
}

Calling achievement screen in Swift

I am having some extreme difficulties calling the achievements screen in game center. I have already set up the achievements in iTunes connect and it pops up fine if I access the achievements screen through the leaderboard first. However; I would like to be able to press a specific achievement button and be directed directly to the achievements screen. Can any one help? I have searched high and low on the internet ( and read through all of the documentation). I have found many resources for implementing leaderboards, but not many resources for implementing achievements in swift. My code is below. Any suggestions for my last two functions?
override func viewDidLoad() {
super.viewDidLoad()
login()
}
func login() {
println("Game Center Login Called")
let localPlayer = GKLocalPlayer.localPlayer()
// Handle the authentication
localPlayer.authenticateHandler = {(Home: UIViewController!, error: NSError!) -> Void in
if Home != nil {
println("Authentication is being processed.")
self.presentViewController(Home, animated: true, completion: nil)
} else {
println("Player has been successfully authenticated.")
}
}
}
func showLeaderboard() {
let gkScore = GKScore(leaderboardIdentifier: "high_Score_Leader_Board")
gkScore.value = Int64(highscore)
GKScore.reportScores([gkScore], withCompletionHandler: ( { (error: NSError!) -> Void in
if (error != nil) {
// handle error
println("Error: " + error.localizedDescription);
} else {
println("Score reported: \(gkScore.value)")
}
}))
var gcViewController: GKGameCenterViewController = GKGameCenterViewController()
gcViewController.gameCenterDelegate = self
gcViewController.viewState = GKGameCenterViewControllerState.Leaderboards
gcViewController.leaderboardIdentifier = "high_Score_Leader_Board"
self.showViewController(gcViewController, sender: self)
self.presentViewController(gcViewController, animated: true, completion: nil)
}
#IBAction func gameCenterButtoPressed(sender: AnyObject) {
showLeaderboard()
}
func gameCenterViewControllerDidFinish(gcViewController: GKGameCenterViewController!)
{
self.dismissViewControllerAnimated(true, completion: nil)
}
func showAchievements() {
// show Achievements screen
}
#IBAction func achievementButtonPressed(sender: AnyObject) {
// Call show achievements function when button pressed
}
Instead of:
gcViewController.viewState = GKGameCenterViewControllerState.Leaderboards
I think what you'll want is:
gcViewController.viewState = GKGameCenterViewControllerState.Achievements
And I found this information in this related tutorial.