Adding a share action to a UIAlertController in Swift - ios

I am building an app with a UIAlertController, and I want to have a button that says "Share" and then opens up something like
it seems easy to do, if it wasn't a sub-button.
My Code:
}
#IBAction func buttonTapped(sender: UIButton) {
var title: String
if sender.tag == correctAnswer {
title = "Correct"
++score
} else {
title = "Wrong"
let ac = UIAlertController(title: title, message: "Your score was \(score).", preferredStyle: .Alert)
ac.addAction(UIAlertAction(title: "Try Again", style: .Default, handler: askQuestion))
ac.addAction(UIAlertAction(title: "Share", style: .Default, handler: share))
presentViewController(ac, animated: true, completion: nil)
gameOver = true
score = 0
}
My share function is currently not defined.

You can define in your completion handler to open an UIActivityController after the UIAlertAction is tapped, nevertheless by default Apple in iPhone not show the share as you want, in iPad yes. With the following code you can show the share after the button is tapped:
let message = "The message"
let alertController = UIAlertController(title: "The title", message: message, preferredStyle: .Alert)
let shareAction = UIAlertAction(title: "Share", style: .Default, handler: { x -> Void in
let firstActivityItem = "Text you want"
let secondActivityItem : NSURL = NSURL(string: "http//:urlyouwant")!
// If you want to put an image
let image : UIImage = UIImage(named: "image.jpg")!
let activityViewController : UIActivityViewController = UIActivityViewController(
activityItems: [firstActivityItem, secondActivityItem, image], applicationActivities: nil)
// Anything you want to exclude
activityViewController.excludedActivityTypes = [
UIActivityTypePostToWeibo,
UIActivityTypePrint,
UIActivityTypeAssignToContact,
UIActivityTypeSaveToCameraRoll,
UIActivityTypeAddToReadingList,
UIActivityTypePostToFlickr,
UIActivityTypePostToVimeo,
UIActivityTypePostToTencentWeibo
]
self.presentViewController(activityViewController, animated: true, completion: nil)
})
alertController.addAction(shareAction)
self.presentViewController(alertController, animated: true, completion: nil)
In the above code I summarize the add more buttons, and I assume that you want the code for iPhone, if you want it too for iPad you can check my answers in this questions:
How do i add this sharing button? IOS8 with swift
Sharing Extensions in IOS Apps
I hope this help you.

Do something like this, if your share method doesn't work
ac.addAction(UIAlertAction(title: "Share", style: .Default, handler: { (action) -> Void in
// Do the Facebook sharing here
let content = FBSDKSharePhotoContent()
content.photo = ....
....
}))

Here is an answer:
I defined the share class as:
func share(action: UIAlertAction!){
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeFacebook) {
let facebook:SLComposeViewController = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
facebook.setInitialText("I just scored \(score) in Flagpoles.")
self.presentViewController(facebook, animated: true, completion: nil)
score = 0
} else {
let alert = UIAlertController(title: "Accounts", message: "Please login to a Facebook account to share.", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}

Related

Add an alertcontroller in a global swift file? [duplicate]

This question already has answers here:
how to create an alert in a swift file model that works for various view controller
(2 answers)
Closed 4 years ago.
I am trying to create a alert box inside the swift file other than the UIViewController file. but I could not create it.
extension NetworkManager {
func showAlert(message: String,from:UIViewController, title: String = "") {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(OKAction)
from.present(alertController, animated: true, completion: nil)
}
}
the above code is for implementing alertcontroller but I don't know how to pass the view controller I need to present so need assistance.
extension UIViewController {
func showAlert(message: String, title: String = "") {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(OKAction)
self.present(alertController, animated: true, completion: nil)
}
}
and use like this
from.showAlert(message:"Your message", title: "Title")
Add a Utilities class in your project.
class Utilities {
static func showSimpleAlert(OnViewController vc: UIViewController, Message message: String) {
//Create alertController object with specific message
let alertController = UIAlertController(title: "App Name", message: message, preferredStyle: .alert)
//Add OK button to alert and dismiss it on action
let alertAction = UIAlertAction(title: "OK", style: .default) { (action) in
alertController.dismiss(animated: true, completion: nil)
}
alertController.addAction(alertAction)
//Show alert to user
vc.present(alertController, animated: true, completion: nil)
}
}
Usage:
Utilities.showSimpleAlert(OnViewController: self, Message: "Some message")
Here is the extension I made. It allows to show either Alert or Action sheet and allows multiple actions "from the box"
extension UIViewController {
func presentAlert(title: String?, message: String, actions: UIAlertAction..., animated: Bool = true) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
actions.forEach { alert.addAction($0) }
self.present(alert, animated: animated, completion: nil)
}
func presentActionSheet(title: String?, message: String, actions: UIAlertAction..., animated: Bool = true) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .actionSheet)
actions.forEach { alert.addAction($0) }
self.present(alert, animated: animated, completion: nil)
}
}
Usage
let delete = UIAlertAction(title: "Delete", style: .destructive, handler: { _ in /* Your code here */})
let cancel = UIAlertAction(title: "Cancel", style: .default, handler: nil)
presentAlert(title: .albumPreferencesDeleteAlertTitle, message: "Very important message", actions: delete, cancel)
This is the more generalise method to show alert on view controller
func showAlert(msg: String, inViewController vc: UIViewController, actions: [UIAlertAction]? = nil, type: UIAlertControllerStyle = .alert, title: String = kAppName) {
let alertType: UIAlertControllerStyle = .alert
let alertTitle = kAppName
let alertVC = UIAlertController(title: alertTitle, message: msg, preferredStyle: alertType)
if let actions = actions {
for action in actions {
alertVC.addAction(action)
}
} else {
let actionCancel = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertVC.addAction(actionCancel)
}
vc.present(alertVC, animated: true, completion: nil)
}
Usage
AppUtilities.showAlert(msg: "Test msg", inViewController: self) //for alert
AppUtilities.showAlert(msg: "Test msg", inViewController: self, actions: [okAction, cancelAction]) //for alert
AppUtilities.showAlert(msg: "Test Msg", inViewController: self, type: .actionSheet) //shows action sheet
You can add this function in extension or create a separate utility class as you want.

Change view when clicking alert button not working

Good day,
This is my code:
#IBAction func logOutAction(sender: AnyObject) {
try! FIRAuth.auth()!.signOut()
let alertController = UIAlertController(title: "Sure?", message: "Are you sure you want to log out?", preferredStyle: .Alert)
let defaultAction = UIAlertAction(title: "Yes", style: .Default, handler: nil)
alertController.addAction(defaultAction)
let defaultAction2 = UIAlertAction(title: "No", style: .Cancel, handler: nil)
alertController.addAction(defaultAction2)
self.presentViewController(alertController, animated: true, completion: nil)
let VC = self.storyboard?.instantiateViewControllerWithIdentifier("loginscreen") as! ViewController //The file that controls the view
self.presentViewController(VC, animated: true, completion: nil)
}
As you can see I want to log out the user when pressing the logout button. When the user clicks logout a UIalert popsup asking if they are sure they want to log out, but when I click okay it doesn't switch back to the loginscree ViewController.
Can anyone help me?
If the last two lines represent the view that you want to present, then you have to execute this code inside the handler of the "Yes" button action:
let defaultAction = UIAlertAction(title: "Yes", style: .Default, handler: { _ in
let VC = self.storyboard?.instantiateViewControllerWithIdentifier("loginscreen") as! ViewController //The file that controls the view
self.presentViewController(VC, animated: true, completion: nil)
})
alertController.addAction(defaultAction)
You need to logout after somebody click "Yes"
let yesActionHandler = { (action:UIAlertAction!) -> Void in
let VC = self.storyboard?.instantiateViewControllerWithIdentifier("loginscreen") as! ViewController //The file that controls the view
self.presentViewController(VC, animated: true, completion: nil)
}
let defaultAction = UIAlertAction(title: "Yes", style: .Default, handler: yesActionHandler)
alertController.addAction(defaultAction)

Calling .presenttoViewController in SKScene in Swift

I'm making a game with Sprite Kit in Swift. When you die in the game it presents the option to share your score on Twitter, Facebook, etc. But since I'm in a SKScene, it doesn't have the member .presentViewController . I need to present the Twitter compose field, is there any way to do this?
Here's the code:
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter) {
let tweetviewcontroller = SLComposeViewController(forServiceType: SLServiceTypeTwitter)
tweetviewcontroller.setInitialText("I Scored \(score) on Cube Falling")
self.presentViewController(tweetviewcontroller, animated: true, completion: nil)
} else {
let alert = UIAlertController(title: "Accounts", message: "Please login to your Twitter account", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Okay", style: UIAlertActionStyle.Default, handler: nil))
alert.addAction(UIAlertAction(title: "Settings", style: UIAlertActionStyle.Default, handler: { (UIAlertAction) in
let settingsURL = NSURL(string: UIApplicationOpenSettingsURLString)
if let url = settingsURL {
UIApplication.sharedApplication().openURL(url)
}
}))
self.presentViewController(alert, animated: true, completion: nil)
}
Here's the error: image of code
Thanks

UIActionSheet crashes on iPad swift

I have the following button action in a toolbar:
#IBAction func share(sender: AnyObject) {
let modifiedURL1 = "http://www.declassifiedandratified.com/search.html?q=\(self.searchBar.text)"
let modifiedURL = modifiedURL1.stringByReplacingOccurrencesOfString(" ", withString: "%20", options: NSStringCompareOptions.LiteralSearch, range: nil)
let alert = UIAlertController(title: "Share", message: "Share your findings", preferredStyle: UIAlertControllerStyle.ActionSheet)
let twBtn = UIAlertAction(title: "Twitter", style: UIAlertActionStyle.Default) { (alert) -> Void in
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter){
var twitterSheet:SLComposeViewController = SLComposeViewController(forServiceType: SLServiceTypeTwitter)
twitterSheet.setInitialText("Look what I found on Declassified and Ratified: \(modifiedURL)")
self.presentViewController(twitterSheet, animated: true, completion: nil)
} else {
var alert = UIAlertController(title: "Accounts", message: "Please login to a Twitter account to share.", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
let fbBtn = UIAlertAction(title: "Facebook", style: UIAlertActionStyle.Default) { (alert) -> Void in
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeFacebook){
var facebookSheet:SLComposeViewController = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
facebookSheet.setInitialText("Look what I found on Declassified and Ratified: \(modifiedURL)")
self.presentViewController(facebookSheet, animated: true, completion: nil)
} else {
var alert = UIAlertController(title: "Accounts", message: "Please login to a Facebook account to share.", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
}
let safariBtn = UIAlertAction(title: "Open in Safari", style: UIAlertActionStyle.Default) { (alert) -> Void in
let URL = NSURL(string: modifiedURL)
UIApplication.sharedApplication().openURL(URL!)
}
let cancelButton = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel) { (alert) -> Void in
println("Cancel Pressed")
}
let textBtn = UIAlertAction(title: "Message", style: UIAlertActionStyle.Default) { (alert) -> Void in
if (MFMessageComposeViewController.canSendText()) {
let controller = MFMessageComposeViewController()
controller.body = "Look what I found on Declassified and Ratified: \(modifiedURL)"
controller.messageComposeDelegate = self
self.presentViewController(controller, animated: true, completion: nil)
}
}
alert.addAction(twBtn)
alert.addAction(fbBtn)
alert.addAction(safariBtn)
alert.addAction(textBtn)
alert.addAction(cancelButton)
self.presentViewController(alert, animated: true, completion: nil)
}
However, this code crashes when called on an iPad with a sigbart crash (that is all I can see in the console). I see this is a common problem but the other solutions have not worked for me. I even set the version to the latest iOS and that didn't fix it. Can someone explain?
On an iPad, an action sheet is a popover. Therefore you must give its UIPopoverPresentationController a sourceView and sourceRect, or barButtonItem, so that it has something to attach its arrow to.

Changing screens by alert in swift

I have no idea how to change screens programatically. I have an alert view and I want to be able to change screen when the user presses the "Ok" button. How do I do this?
Here is my new code:
func showAlertController(){
let tilte = "My Medication"
let message = NSLocalizedString("Go through Medication guide?", comment: "")
let cancelButtonTitle = NSLocalizedString("Dismiss", comment: "")
let otherButtonTitle = NSLocalizedString("Ok", comment: "")
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: cancelButtonTitle, style: .Cancel){ action in
NSLog("User said no")}
let otherAction = UIAlertAction(title: otherButtonTitle, style: .Default){action in
// I know I need to put something in here.
let appointment = Appointment()
self.presentViewController(appointment, animated:true, completion:nil)
}
alertController.addAction(cancelAction)
alertController.addAction(otherAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
However now I get a bug saying:
Thread 1: EXC_BAD_INSTRUCTION(code=EXC_l1386_INVOP,subcode=0x0)
Add presentViewController inside UIAlertAction closure for "Ok" button, it means that the button is pressed and so you do your stuffs for the button being pressed inside the block.
class MainViewController: UIViewController {
...
...
func showAlertController(){
let tilte = "My Medication"
let message = NSLocalizedString("Go through Medication guide?", comment: "")
let cancelButtonTitle = NSLocalizedString("Dismiss", comment: "")
let otherButtonTitle = NSLocalizedString("Ok", comment: "")
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: cancelButtonTitle, style: .Cancel){ action in
NSLog("User said no")}
let otherAction = UIAlertAction(title: otherButtonTitle, style: .Default){action in
// I know I need to put something in here.
let appointmentViewController = AppointmentViewController()
self.presentViewController(appointmentViewController, animated:true, completion:nil)
}
alertController.addAction(cancelAction)
alertController.addAction(otherAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
...
...
}
class AppointmentViewController: UIViewController {
}

Resources