14

This is my alert that works perfectly. I want to add an image to the alert that shows up along side the text when the alert is presented and I'm in an SKScene in SpriteKit if it makes a difference.

var alertController = UIAlertController(title: "How to Skate", message: "Tap the screen to perform a trick and jump over the obsticles (You can grind on rails) The game will end when you hit a highlighted red, orange or yellow obstacle. That's it! + Image", preferredStyle: UIAlertControllerStyle.Alert)     
alertController.addAction(UIAlertAction(title: "Cool!", style: UIAlertActionStyle.Cancel, handler: nil))
self.view?.window?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)

7 Answers7

17

You can add a UIImageView as a subview to your UIAlertController.

var imageView = UIImageView(frame: CGRectMake(220, 10, 40, 40))
imageView.image = yourImage
alert.view.addSubview(imageView)

This is how you do in UIAlertController:

let alertMessage = UIAlertController(title: "My Title", message: "My Message", preferredStyle: .Alert)

let image = UIImage(named: "myImage")
var action = UIAlertAction(title: "OK", style: .Default, handler: nil)
action.setValue(image, forKey: "image")
alertMessage .addAction(action)

self.presentViewController(alertMessage, animated: true, completion: nil)
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Abhinav
  • 37,684
  • 43
  • 191
  • 309
  • 1
    These approaches aren't compliant. It effectively adds an image to a button area and affecting the sizing of other buttons in the alert view. It's also likely the accessibility for this approach isn't compliant either. Apple should have made it possible to do this out of the box, but without that option, a custom alert made from a `UIView` seems like the best approach and has the benefit of the ability to control all elements. – user4806509 Aug 05 '17 at 22:03
6
    let alertMessage = UIAlertController(title: "My Title", message: "", preferredStyle: .alert)
    let action = UIAlertAction(title: "OK", style: .default, handler: nil)
    action.setValue(UIImage(named: "task1.png")?.withRenderingMode(UIImageRenderingMode.alwaysOriginal), forKey: "image")
    alertMessage .addAction(action)
    self.present(alertMessage, animated: true, completion: nil)

Swift 3

Mikhail Baynov
  • 121
  • 1
  • 3
4

You can do like this.

    let imageView = UIImageView(frame: CGRectMake(220, 10, 40, 40))
   // imageView.image = UIImage(named: "ic_no_data")
    let alertMessage = UIAlertController(title: "My Title", message: "", preferredStyle: .Alert)

    let image = UIImage(named: "Image")
    let action = UIAlertAction(title: "OK", style: .Default, handler: nil)
    action.setValue(image, forKey: "image")
    alertMessage .addAction(action)

    self.presentViewController(alertMessage, animated: true, completion: nil)
    alertMessage.view.addSubview(imageView)
Kushal Shrestha
  • 775
  • 1
  • 10
  • 21
2

Adding an image to a UIAlertController

Please try below code Swift 4 +

  1. Add alertView Controller

    let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.alert) let image = UIImage(named:"feet")! alert.addImage(image: image) alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)) // show the alert self.present(alert, animated: true, completion: nil)

  2. Add Extension UIAlertController

    func addImage(image: UIImage) {

    let maxSize = CGSize(width: 240, height: 244)
    let imgSize = image.size
    var ratio:CGFloat!
    if (imgSize.width > imgSize.height){
        ratio = maxSize.width / imgSize.width
    }else {
        ratio = maxSize.height / imgSize.height
    }
    let scaleSize = CGSize(width: imgSize.width*ratio, height: imgSize.height*ratio)
    var resizedImage = image.imageWithSize(scaleSize)
    
    if (imgSize.height > imgSize.width) {
        let left = (maxSize.width - resizedImage.size.width) / 2
        resizedImage = resizedImage.withAlignmentRectInsets(UIEdgeInsetsMake(0, -left, 0, 0))
    }
    
    let imgAction = UIAlertAction(title: "", style: .default, handler: nil)
    imgAction.isEnabled = false
    imgAction.setValue(resizedImage.withRenderingMode(.alwaysOriginal), forKey: "image")
    
    self.addAction(imgAction)
    

    }

Add image view extension

extension UIImage {

func imageWithSize(_ size:CGSize) -> UIImage {
    var scaledImageRect = CGRect.zero

    let aspectWidth:CGFloat = size.width / self.size.width
    let aspectHeight:CGFloat = size.height / self.size.height
    let aspectRatio:CGFloat = min(aspectWidth, aspectHeight)

    scaledImageRect.size.width = self.size.width * aspectRatio
    scaledImageRect.size.height = self.size.height * aspectRatio
    scaledImageRect.origin.x = (size.width - scaledImageRect.size.width) / 2.0
    scaledImageRect.origin.y = (size.height - scaledImageRect.size.height) / 2.0

    UIGraphicsBeginImageContextWithOptions(size, false, 0)

    self.draw(in: scaledImageRect)

    let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return scaledImage!
}

}

1

If you're willing to use private APIs you could use the private attributedMessage property to set an attributed string as message containing an image:

Source: https://github.com/JaviSoto/iOS10-Runtime-Headers/blob/master/Frameworks/UIKit.framework/UIAlertController.h

let actionSheet = UIAlertController(title: "title", message: nil, preferredStyle: .actionSheet)

let str = NSMutableAttributedString(string: "Message\n\n", attributes: [NSAttributedStringKey.font: UIFont.preferredFont(forTextStyle: .caption1), NSAttributedStringKey.foregroundColor: UIColor.gray])

let attachment = NSTextAttachment()

attachment.image = --> yourImage <--

str.append(NSAttributedString(attachment: attachment))

actionSheet.setValue(str, forKey: "_attributedMessage")

Again, this is a private API and therefore could change in any release without notice. To be used with caution!

JonasG
  • 9,274
  • 12
  • 59
  • 88
1

SWIFT 4 +

        let refreshAlert = UIAlertController(title: "Unlike Article", message: "Are you sure you want to unlike this Article?", preferredStyle: UIAlertControllerStyle.alert)



        let cancel = UIAlertAction(title:  "CANCEL", style: .default, handler: { (action: UIAlertAction!) in



            return
        })

        let image = #imageLiteral(resourceName: "dislike_icon").resizedImage(newSize: CGSize(width: 25, height: 25))
        let unLike = UIAlertAction(title: "UNLIKE", style: .destructive, handler: { (action: UIAlertAction!) in
            self.articleUnLiking()


            return
        })
        unLike.setValue(image.withRenderingMode(UIImageRenderingMode.alwaysOriginal), forKey: "image")
        refreshAlert.addAction(cancel)
        refreshAlert.addAction(unLike)
        self.present(refreshAlert, animated: true, completion: nil)

NOTE :- Again, this is a private API and therefore could change in any release without notice. To be used with caution!

THANKS

Sachin Rasane
  • 1,501
  • 12
  • 17
1

Currently there isn't really a proper way of doing that with UIAlertController without using private api or other hacks because according to documentation you should not modify view hierarchy of alert view controller. So the best solution would be to create a custom view for that. However if you do not care about some additional borders then using attributed string in UITextField works:

alertController.addTextField { field in
    let attachment = NSTextAttachment()
    attachment.image = image
    attachment.bounds = CGRect(x: 0, y: 0, width: 226, height: 226)
    field.attributedPlaceholder = NSAttributedString(attachment: attachment)
    field.textAlignment = .center
    field.isEnabled = false
}
Leszek Szary
  • 9,763
  • 4
  • 55
  • 62