I am having trouble understanding the UIKit crash reports that I am receiving:
Is there a way of finding out what line of code caused this:
Crashed: com.apple.main-thread
0 UIKit 0x195694264 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke + 444
1 UIKit 0x1955d0950 _runAfterCACommitDeferredBlocks + 292
2 UIKit 0x1955c29ec _cleanUpAfterCAFlushAndRunDeferredBlocks + 528
3 UIKit 0x195336648 _afterCACommitHandler + 132
4 CoreFoundation 0x18f1c09a8 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
5 CoreFoundation 0x18f1be630 __CFRunLoopDoObservers + 372
6 CoreFoundation 0x18f1bea7c __CFRunLoopRun + 956
7 CoreFoundation 0x18f0eeda4 CFRunLoopRunSpecific + 424
8 GraphicsServices 0x190b58074 GSEventRunModal + 100
9 UIKit 0x1953a9058 UIApplicationMain + 208
10 FlexConnect 0x1001b48c8 main (AppDelegate.swift:20)
11 libdyld.dylib 0x18e0fd59c start + 4
The error itself is:
Crashed: com.apple.main-thread
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000010
EDIT:
Based of the answer below, I'm wondering if it is advisable to use:
func topMostController() -> UIViewController {
var topController: UIViewController = UIApplication.sharedApplication().keyWindow!.rootViewController!
while (topController.presentedViewController != nil) {
topController = topController.presentedViewController!
}
return topController
}
and always call
let topVC = topMostController().dismiss(animated: true, completion: nil)
everywhere in my app where I currently have self.dismiss(animated: true, completion: nil)?
Is this a necessary check or how can I pin down where self.dismiss is having an issue?
Some sample dismissals:
#IBAction func returnToDash(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
let pending = UIAlertController(title: "\n\n\n\(title)", message: nil, preferredStyle: .alert)
displayActivityAlertWithCompletion2(ViewController: self, pending: pending){_ in
Helper_StatusCheck.doSync(_cleanSync: false){
Prefs.is_Syncing = false
DispatchQueue.main.async {
pending.dismiss(animated: true){
Toast(text: "Upload sync completed").show()
self.dismiss(animated: true, completion: nil)
}
}
}
}
where displayActivityAlertWithCompletion2 looks like:
public func displayActivityAlertWithCompletion2(ViewController: UIViewController, pending: UIAlertController, completionHandler: #escaping ()->())
{
//let pending = UIAlertController(title: "\n\n\n"+title, message: nil, preferredStyle: .alert)
//create an activity indicator
let indicator = UIActivityIndicatorView(frame: pending.view.bounds)
indicator.autoresizingMask = [.flexibleWidth, .flexibleHeight]
indicator.color = UIColor(rgba: Palette.loadingColour)
//add the activity indicator as a subview of the alert controller's view
pending.view.addSubview(indicator)
indicator.isUserInteractionEnabled = false
// required otherwise if there buttons in the UIAlertController you will not be able to press them
indicator.startAnimating()
ViewController.present(pending, animated: true, completion: completionHandler)
}
EDIT 2 :
Some sample popover methods in my app:
#IBAction func search(_ sender: UIButton) {
if let popView = UIStoryboard(name: "AssetCommon", bundle: nil).instantiateViewController(withIdentifier: "searchPop") as? searchPopVC {
popView.delegate = self
popView.modalPresentationStyle = .popover;
popView.popoverPresentationController?.delegate = self
popView.popoverPresentationController?.barButtonItem = searchButton
popView.popoverPresentationController?.permittedArrowDirections = .any
popView.preferredContentSize = CGSize(width: 300, height: 70)
self.present(popView, animated: true, completion: nil)
}
}
and search pop:
class searchPopVC: UIViewController
{
#IBOutlet weak var searchBar: UISearchBar!
weak var delegate: SearchPopDelegate?
override func viewDidLoad()
{
super.viewDidLoad()
searchBar.delegate = self;
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
#IBAction func performSearch(_ sender: UIButton)
{
let term = searchBar.text ?? "";
delegate?.performSearch(with: term)
self.dismiss(animated: true, completion: nil);
}
}
extension searchPopVC: UISearchBarDelegate
{
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
let term = searchBar.text ?? "";
delegate?.performSearch(with: term);
self.dismiss(animated: true, completion: nil)
}
}
You won't be able to find the line of code from this crash. However, this crash happens when the view controller you use to call dismiss(animated:completion:) is removed from the view hierarchy prior to the animation completing.
Depending on how your code is setup, you can try to request a view controller higher up to call the dismissal. Another solution could be to retain the view controller in a property until your for sure done with it.
Edit: 1/5/18
In response to the comments, here is an example of how a function can be made for view controllers that logs an event and dismisses.
extension UIViewController {
func dismissAndLog(animated: Bool, completion: (() -> ())? = nil) {
// Here are two examples of how your view controller can be identified.
// let id = title
let id = String(describing: type(of: self))
CLSLogv("Dismissed View Controller: %#", getVaList([id]))
dismiss(animated: animated, completion: completion)
}
}
I'm not entirely familiar with Crashlytics or their API, so if this logging is giving you issues, you can check out these links.
https://docs.fabric.io/apple/crashlytics/enhanced-reports.html#custom-logging-in-swift
How to use Crashlytics logging in Swift?
Also I don't know how they provide the data to you, so I can't explain to you the best way to parse it. However certainly the timestamps can be successfully used as a final solution. You can also try emailing their support asking for the best way to map these logs to the crash.
var topController: UIViewController = UIApplication.sharedApplication().keyWindow!.rootViewController!
This many exclamation marks should tell you that there is something not great about this code. Guard and check these assumptions because any one of them may blow up.
Other than that, what gives you some really weird errors, is if you do these kind of dismiss/pop/present actions as part of a defered block like you are doing in Helper_StatusCheck.doSync. There can be all kinds of changes to the navigation stack in between and your assumptions may not hold.
Related
Im using event kit to create a reminder, but when I press add or cancel the window does not close. if I go into the calendars app I can see the item in there. I've tried adding "editviewDelegate = self" but I always get an error saying "Cannot assign value of type 'ViewController?' to type 'EKEventEditViewDelegate"
import UIKit
import EventKit
import EventKitUI
class ViewController: UIViewController, EKEventViewDelegate {
func eventViewController(_ controller: EKEventViewController, didCompleteWith action: EKEventViewAction) {
controller.dismiss(animated: true, completion: nil)
}
let store = EKEventStore()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addnew))
}
#objc func addnew() {
store.requestAccess(to: .event) { [weak self] success, error in
if success, error == nil {
DispatchQueue.main.async {
guard let store = self?.store else {return}
let othervc = EKEventEditViewController()
othervc.eventStore = store
othervc.event = EKEvent(eventStore: store)
self?.present(othervc, animated: true, completion: nil)
}
}
}
}
i'm trying to make a action in other storyboard but i'm getting this error
2019-12-24 07:44:32.861248-0800 test[1588:142069] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x600003631e50 UIView:0x7fc09d715410.width == - 16 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600003631e50 UIView:0x7fc09d715410.width == - 16 (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in
<UIKitCore/UIView.h> may also be helpful.
i'm new in ios development, i know that other request are posted in stack overflow but i'm don't understand how to revolve my problem.
i create un Alert.storyboard with nothing
AlertViewController.swift with :
import UIKit
class AlertViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
a()
}
func a() {
let alert = UIAlertController(title: "Something", message: nil, preferredStyle: .actionSheet)
let opt1 = UIAlertAction( title: "Action 1", style: .default) { (action) in
print("dskhgohg")
self.dismiss(animated: true)
}
alert.addAction(opt1)
present( alert, animated: true, completion: nil )
}
}
AlertService.swift
import UIKit
class AlertService {
func alert() -> AlertViewController {
let storyboard = UIStoryboard(name: "Alert", bundle: .main)
let alertVC = storyboard.instantiateViewController(identifier: "AlertVC") as! AlertViewController
return alertVC
}
}
and i added a button in Main.storyboard with action in viewController
let alertService = AlertService()
#IBAction func btn() {
let alertVC = alertService.alert()
present(alertVC, animated: true)
print("dsgjodig")
}
maybe i shoud not action sheet in viewDidAppear
All action sheets do that. It’s an Apple bug. It has no effect on your app’s functionality. Ignore it and move on.
I need to present a modal VC that sets a property in my presenting VC, and then I need to do something with that value back in the presenting VC. I have to be able to pass pointers to different properties to this function, so that it's reusable. I have the code below (KeyPickerTableViewController is the modal VC).
It should work, except not, because the line after present(picker... gets executed immediately after the picker is presented.
How do I get my presenting VC to "wait" until the modal VC is dismissed?
#objc func fromKeyTapped(_ button: UIBarButtonItem) {
print("from tapped")
setKey(for: &sourceKey, presentingFrom: button)
}
#objc func toKeyTapped(_ button: UIBarButtonItem) {
print("from tapped")
setKey(for: &destKey, presentingFrom: button)
}
fileprivate func setKey(for key: inout Key!, presentingFrom buttonItem: UIBarButtonItem) {
let picker = KeyPickerTableViewController()
picker.delegate = self
picker.modalPresentationStyle = .popover
picker.popoverPresentationController?.barButtonItem = buttonItem
present(picker, animated: true, completion: nil)
if let delKey = delegatedKey {
key = delKey
}
}
You could use delegate pattern or closure.
I would do the following
1. I would not use inout pattern, I would first call the popover and then separately update what is needed to be updated
2. In KeyPickerTableViewController define property var actionOnDismiss: (()->())? and setting this action to what we need after initialisation of KeyPickerTableViewController
I could show it in code, but the abstract you've shown is not clear enough to come up with specific amendments. Please refer the illustration below.
import UIKit
class FirstVC: UIViewController {
var key = 0
#IBAction func buttonPressed(_ sender: Any) {
let vc = SecondVC()
vc.action = {
print(self.key)
self.key += 1
print(self.key)
}
present(vc, animated: true, completion: nil)
}
}
class SecondVC: UIViewController {
var action: (()->())?
override func viewDidLoad() {
onDismiss()
}
func onDismiss() {
action?()
}
}
While presenting VC, add dismissing modal VC action in its completion handler, so that Viewcontroller will be presented after dismissal is completed
present(picker, animated: true, completion: { (action) in
//dismissal action
if let delKey = delegatedKey {
key = delKey
}
})
I am having this error below when trying to sign with cognito aws, it actually checks for the user credentials but crashes the app on its run time.
I want to show my mainView after a successful login and I don't know what I am missing but the app crashes when I run it.
I hope I explained myself well.
2017-02-19 19:46:12.770 HDPTestV2[28298:5420991] -[AWSTask exception]: unrecognized selector sent to instance 0x60000006ab40
2017-02-19 19:46:12.773 HDPTestV2[28298:5420991] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[AWSTask exception]: unrecognized selector sent to instance 0x60000006ab40'
*** First throw call stack:
(
0 CoreFoundation 0x000000010b32dd4b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010ad9621e objc_exception_throw + 48
2 CoreFoundation 0x000000010b39df04 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x000000010b2b3005 ___forwarding___ + 1013
4 CoreFoundation 0x000000010b2b2b88 _CF_forwarding_prep_0 + 120
5 HDPTestV2 0x0000000109d9f8f7 __35-[AWSIdentityManager completeLogin]_block_invoke_2 + 263
6 libdispatch.dylib 0x000000010d84f978 _dispatch_call_block_and_release + 12
7 libdispatch.dylib 0x000000010d8790cd _dispatch_client_callout + 8
8 libdispatch.dylib 0x000000010d8598a4 _dispatch_main_queue_callback_4CF + 406
9 CoreFoundation 0x000000010b2f1e49 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
10 CoreFoundation 0x000000010b2b737d __CFRunLoopRun + 2205
11 CoreFoundation 0x000000010b2b6884 CFRunLoopRunSpecific + 420
12 GraphicsServices 0x000000010f79ca6f GSEventRunModal + 161
13 UIKit 0x000000010b751c68 UIApplicationMain + 159
14 HDPTestV2 0x0000000109d9c8af main + 111
15 libdyld.dylib 0x000000010d8c568d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
--> SignInController.swift
// SignInViewController.swift
// HDPTestV2
//
// Created by Gael Wamba Musikingala on 2017/02/19.
// Copyright © 2017 Gael Wamba Musikingala. All rights reserved.
//
import UIKit
import AWSMobileHubHelper
import AWSCognitoIdentityProvider
class SignInViewController: UIViewController {
#IBOutlet weak var usernameField: UITextField!
#IBOutlet weak var passwordField: UITextField!
var passwordAuthenticationCompletion: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func onSignIn(_ sender: UIButton) {
self.handleCustomSignIn()
}
func handleLoginWithSignInProvider(signInProvider: AWSSignInProvider){
AWSIdentityManager.defaultIdentityManager().loginWithSign(signInProvider) { (result:Any?, error: Error?) in
if error == nil {
/* Handle successful login. */
DispatchQueue.main.async(execute:{
let mainViewController = self.storyboard!.instantiateViewController(withIdentifier: "MainView") as! MainViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = mainViewController
appDelegate.window?.makeKeyAndVisible()
})
}
print("Login with signin provider result = \(result), error = \(error)")
}
}
}
---> SignInViewControllerExtensions.swift
import Foundation
import AWSCognitoIdentityProvider
import AWSMobileHubHelper
// Extension containing methods which call different operations on Cognito User Pools (Sign In, Sign Up, Forgot Password)
extension SignInViewController {
func handleCustomSignIn() {
// set the interactive auth delegate to self, since this view controller handles the login process for user pools
AWSCognitoUserPoolsSignInProvider.sharedInstance().setInteractiveAuthDelegate(self)
self.handleLoginWithSignInProvider(signInProvider: AWSCognitoUserPoolsSignInProvider.sharedInstance())
}
func handleUserPoolSignUp () {
let storyboard = UIStoryboard(name: "UserPools", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "SignUp")
self.present(viewController, animated:true, completion:nil);
}
func handleUserPoolForgotPassword () {
let storyboard = UIStoryboard(name: "UserPools", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "ForgotPassword")
self.present(viewController, animated:true, completion:nil);
}
}
// Extension to adopt the `AWSCognitoIdentityInteractiveAuthenticationDelegate` protocol
extension SignInViewController: AWSCognitoIdentityInteractiveAuthenticationDelegate {
// this function handles the UI setup for initial login screen, in our case, since we are already on the login screen, we just return the View Controller instance
func startPasswordAuthentication() -> AWSCognitoIdentityPasswordAuthentication {
return self as AWSCognitoIdentityPasswordAuthentication
}
// prepare and setup the ViewController that manages the Multi-Factor Authentication
func startMultiFactorAuthentication() -> AWSCognitoIdentityMultiFactorAuthentication {
let storyboard = UIStoryboard(name: "UserPools", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "MFA")
DispatchQueue.main.async(execute: {
self.present(viewController, animated:true, completion:nil);
})
return viewController as! AWSCognitoIdentityMultiFactorAuthentication
}
}
// Extension to adopt the `AWSCognitoIdentityPasswordAuthentication` protocol
extension SignInViewController: AWSCognitoIdentityPasswordAuthentication {
func getDetails(_ authenticationInput: AWSCognitoIdentityPasswordAuthenticationInput,
passwordAuthenticationCompletionSource: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>){
self.passwordAuthenticationCompletion = passwordAuthenticationCompletionSource
}
func didCompleteStepWithError(_ error: Error?){
if let error = error {
let errorString = (error as NSError).userInfo
DispatchQueue.main.async(execute: {
UIAlertView(title: errorString["__type"] as? String,
message: errorString["message"] as? String,
delegate: nil,
cancelButtonTitle: "Ok").show()
})
}
}
}
// Extension to adopt the `AWSCognitoUserPoolsSignInHandler` protocol
extension SignInViewController: AWSCognitoUserPoolsSignInHandler {
func handleUserPoolSignInFlowStart() {
// check if both username and password fields are provided
guard let username = self.usernameField.text, !username.isEmpty,
let password = self.passwordField.text, !password.isEmpty else {
DispatchQueue.main.async(execute: {
UIAlertView(title: "Missing UserName / Password",
message: "Please enter a valid user name / password.",
delegate: nil,
cancelButtonTitle: "Ok").show()
})
return
}
// set the task completion result as an object of AWSCognitoIdentityPasswordAuthenticationDetails with username and password that the app user provides
self.passwordAuthenticationCompletion?.set(result: AWSCognitoIdentityPasswordAuthenticationDetails(username: username, password: password))
}
}
--> AppDelegate.swift
// AppDelegate.swift
// HDPTestV2
//
// Created by Gael Wamba Musikingala on 2017/02/18.
// Copyright © 2017 Gael Wamba Musikingala. All rights reserved.
//
import UIKit
import AWSMobileHubHelper
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return AWSMobileClient.sharedInstance.didFinishLaunching(application: application, withOptions: launchOptions as [NSObject : AnyObject]?)
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
return AWSMobileClient.sharedInstance.withApplication(application: application, withURL: url as NSURL, withSourceApplication: sourceApplication, withAnnotation: annotation as AnyObject)
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
AWSMobileClient.sharedInstance.applicationDidBecomeActive(application: application)
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
DispatchQueue.main.async(execute:{
let mainViewController = self.storyboard!.instantiateViewController(withIdentifier: "MainView") as! MainViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = mainViewController
appDelegate.window?.makeKeyAndVisible()
})
Comment this line for some time and print something here and check you reach there or not?
I am looking for a way to call a custom alert view from multiple view controllers. So far I have made several different attempts without success.
I created an alert view with an interface builder that works fine on one view controller but not the other.
I then tried creating the alert view programmatically thinking it may have something to do with the outlets not being connected on the other view controller. This one also worked on one view controller and not the other.
I made a separate swift file and made a public function and the same result. With this last method, I am able to successfully re-use a regular UIAlertController on multiple view controllers but that is not exactly what I am looking for.
With the first two methods, I do not get any compiling errors. The app runs fine and then crashes when I call the alert from another view controller.
Thanks in advance for any input!
EDIT:
This example works when I put it in another swift file.
public func showSimpleAlert(title: String, message: String?, presentingController: UIViewController) {
if IS_OS_8_OR_LATER() {
let controller = UIAlertController(title: title, message: message, preferredStyle: .Alert)
controller.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: { (action) -> Void in
}))
presentingController.presentViewController(controller, animated: true, completion: nil)
} else {
let alert = UIAlertView(title: title, message: message, delegate: nil, cancelButtonTitle: "OK")
alert.show()
}
}
This is the one I want to work on.
public func showAlert(oMsg: String, oTitle:String) {
alertView.backgroundColor = UIColor.whiteColor()
alertView.layer.cornerRadius = 25
alertTitleLabel.text = oTitle as String
alertTitleLabel.font = UIFont(name: "Open-Sans-Bold", size: 20)
alertTitleLabel.textColor = UIColor.blackColor()
alertTitleLabel.textAlignment = .Center
alertTitleLabel.numberOfLines = 1
alertTitleLabel.frame = CGRectMake(25, 60, 264, 112)
alertLabel.text = oMsg as String
alertLabel.font = UIFont(name: "Open-Sans", size: 20)
alertLabel.textColor = UIColor.blackColor()
alertLabel.textAlignment = .Center
alertLabel.numberOfLines = 4
alertLabel.frame = CGRectMake(25, 130, 264, 112)
okButton.setTitle("OK", forState: .Normal)
okButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
okButton.frame = CGRectMake(60, 230, 197, 75)
okButton.addTarget(UIViewController.self, action:#selector(LoginViewController.buttonAction(_:)), forControlEvents: .TouchUpInside)
}
I will give the answer for a simple custom alertview which is basically a modified uiviewcontroller. you can use a uiviewcontroller as a uialertviewcontroller as follow.
Simple AlertView::
The AlertVC:
import UIKit
class ErrorAlert: UIViewController {
var titlenote:String = ""
var message:String = ""
#IBOutlet weak var cancelBtn: UIButton!
#IBOutlet weak var messageHolder: UILabel!
#IBOutlet weak var imageHolder: UIImageView!
#IBOutlet weak var titleHolder: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.black.withAlphaComponent(0.7)
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.messageHolder.text = self.message
self.titleHolder.text = self.titlenote
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func dismiss(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
}
This viewcontroller can be reuse in any vc and any number of times.
Useage Example::
let alertController = self.storyboard?.instantiateViewController(withIdentifier: "erroralert") as! ErrorAlert
alertController.titlenote = "Invalid login"
alertController.message = "Invalid facebook account."
alertController.providesPresentationContextTransitionStyle = true
alertController.definesPresentationContext = true
alertController.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
alertController.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
self.present(alertController, animated: true, completion: nil)
I have made the background of the alertviewvc semitransparent by setting the alpha value.
Actual Display ::
You can make more complex alertview by this method but for reusability you have apply some logic as the button actions will be different for different viewcontroller. Example -- Sometime you can use the alertview for logout alert or sometime for submitting a form .So in both cases the action will be different so for reusability you have to write extra logic.
Another alertView::
I hope my answer will help you.:)