3

My app's crashing when trying to present a UIAlertController.

I have a UIViewController that gets presented modally, then on that presented view controller when a certain button is tapped I want to present a actionSheet alert.

Somehow the app crashes when doing this and I cannot figure it out why.

Here's the code:

let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
alertController.addAction(UIAlertAction(title: "Image from Camera", style: .default, handler: { (_) in
    let cameraController = CameraController()
    self.present(cameraController, animated: true, completion: nil)
}))
alertController.addAction(UIAlertAction(title: "Image from Library", style: .default, handler: {(_) in
    let imagePickerController = UIImagePickerController()
    imagePickerController.delegate = self
    imagePickerController.allowsEditing = true
    self.present(imagePickerController, animated: true, completion: nil)
}))
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
alertController.view.tintColor = UIColor.rgb(red: 46, green: 94, blue: 120)
self.present(alertController, animated: true, completion: nil)

The crash log:

libc++abi.dylib: terminating with uncaught exception of type NSException

When I backtrace the error it shows this:

    * thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00000001101a7fce libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00000001101e1150 libsystem_pthread.dylib`pthread_kill + 333
    frame #2: 0x000000010fe650e7 libsystem_c.dylib`abort + 127
    frame #3: 0x000000010fbf791f libc++abi.dylib`abort_message + 245
    frame #4: 0x000000010fbf7abb libc++abi.dylib`default_terminate_handler() + 265
    frame #5: 0x0000000109b341be libobjc.A.dylib`_objc_terminate() + 97
    frame #6: 0x000000010fc13159 libc++abi.dylib`std::__terminate(void (*)()) + 8
    frame #7: 0x000000010fc12e0a libc++abi.dylib`__cxa_rethrow + 99
    frame #8: 0x0000000109b340dc libobjc.A.dylib`objc_exception_rethrow + 40
    frame #9: 0x000000010a424a39 CoreFoundation`CFRunLoopRunSpecific + 537
    frame #10: 0x0000000112faf9c6 GraphicsServices`GSEventRunModal + 62
    frame #11: 0x000000010bd325e8 UIKit`UIApplicationMain + 159
    frame #13: 0x000000010fd92d81 libdyld.dylib`start + 1
    frame #14: 0x000000010fd92d81 libdyld.dylib`start + 1

I even tried to dispatch on main queue the presentation, but it still doesn't work.

Any hint?

Thank you.

EDIT

In order to filter some problems I've implemented a simple alert controller and it still crash using .actionSheet but not with .alert

let alert = UIAlertController(title: "title", message: "message", preferredStyle: UIAlertControllerStyle.actionSheet)
present(refreshAlert, animated: true, completion: nil)

Doing this it crashes, but if I use .alert it does not.

Why is this happening

Ivan Cantarino
  • 3,058
  • 4
  • 34
  • 73
  • I don't know if the problem is presenting an alert controller from an already presented view controller; but I have done this before with any problem – Ivan Cantarino Nov 08 '17 at 09:52
  • 1
    Check if this code is in background thread or is being called from background thread. – Nitish Nov 08 '17 at 09:55
  • @Nitish as I mentioned, I have tried to present it dispatching in the main thread and it still crashes. – Ivan Cantarino Nov 08 '17 at 09:56
  • May or may not be related... one thing I noticed is UIColor.rgb(). Is this your own custom extension method for UIColor as normally color values provided are between 0 and 1? good luck – Louis Leung Nov 08 '17 at 09:57
  • The problem isn't the UIColor extension, it could be, but I just tried with default colors and it still crashes. – Ivan Cantarino Nov 08 '17 at 09:59
  • `let cameraController = CameraController()`. You must instantiate it or simple call the `performSegue`, if your desired view controller is connected. – Mannopson Nov 08 '17 at 10:28
  • @IvanCantarino `let alert = UIAlertController(title: "title", message: "message", preferredStyle: .actionSheet) present(alert, animated: true, completion: nil)` – Mannopson Nov 08 '17 at 11:05

2 Answers2

7

So I figure out the problem.

Unfortunately Xcode doesn't help with their crash logs, which are vague.

The problem is that since I'm testing this UIAlertController on an iPad I should implement the alert controller's source view.

In order to do so, I've added the following code and everything is working as expected:

if UIDevice.current.userInterfaceIdiom == .pad {
    guard let button = self.header?.profileImageButton else { return }
    alertController.popoverPresentationController?.permittedArrowDirections = .right
    alertController.popoverPresentationController?.sourceView = button
}
self.present(alertController, animated: true, completion: nil)
Ivan Cantarino
  • 3,058
  • 4
  • 34
  • 73
0

Alert PopUp

This is help me i think this is help for you

     let refreshAlert = UIAlertController(title: "Refresh", message: "All data will be lost.", preferredStyle: UIAlertControllerStyle.alert)

    refreshAlert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action: UIAlertAction!) in
        print("Handle Ok logic here")
    }))

    refreshAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { (action: UIAlertAction!) in
        print("Handle Cancel Logic here")
    }))

    present(refreshAlert, animated: true, completion: nil)

Action Sheet

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

     create an action
       let firstAction: UIAlertAction = UIAlertAction(title: "First Action", style: .default) { action -> Void in

            print("First Action pressed")
        }

        let secondAction: UIAlertAction = UIAlertAction(title: "Second Action", style: .default) { action -> Void in

            print("Second Action pressed")
        }

        let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .cancel) { action -> Void in }

    // add actions
    actionSheetController.addAction(firstAction)
    actionSheetController.addAction(secondAction)
    actionSheetController.addAction(cancelAction)

     present an actionSheet...
    present(actionSheetController, animated: true, completion: nil)

}
seggy
  • 1,176
  • 2
  • 18
  • 38
Sunil
  • 1
  • 3
  • @seggy : Not a great job editing this :) – Nitish Nov 08 '17 at 10:30
  • I am guessing you are new to StackOverflow. The answer which you have shared is not the one OP is looking for. OP already knows what you are suggesting but the issue he is facing lies in the code. It could also come in the same code which you have written. – Nitish Nov 08 '17 at 10:52