initially i am showing one alert when click on yes it will show second alert, in second alert when user press on reset i want show progress view and call service in this progress view is not showing only service call is happening i want to show progress view also, so how how can i show progress view after press ok in second alert?
func makeServiceCall()
{
Utility.showGlobalProgressHUD(withTitle: "Loading...")
HTTPRequest.serviceReq(newPin: "129354") { (ResetModel) in
Utility.dismissGlobalHUDInMainThread()
Utility.showAlertMessageInMainThread(title: " Reset", msg: "Your request to reset has been successfully completed.")
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
Utility.confirmationActionSheetMsg(title: "First Alert", msg: "alertMsg", okActionTitle: "Yes", cancelActionTitle: "Cancel", success:
{
Utility.showAlertViewWithTextField(title: "Second Alert", msg: "alertMsg", okActionTitle: "Reset", cancelActionTitle: "Cancel", success: {
self.makeServiceCall()
}, cancel: {
print("Canceled by user")
})
}
}) {
print("cancel")
}
}
utility file is -
class Utility{
static func showGlobalProgressHUD(withTitle title: String?) -> MBProgressHUD?
{
let window: UIWindow? = UIApplication.shared.windows.last
let hud = MBProgressHUD.showAdded(to: window, animated: true)
hud?.labelText = title
hud?.dimBackground = true
hud?.cornerRadius = 7
hud?.margin = 30
hud?.detailsLabelFont = UIFont.boldSystemFont(ofSize: 15)
window?.isUserInteractionEnabled = true
hud?.isUserInteractionEnabled = true;
return hud
}
static func confirmationActionSheetMsg(title: String, msg: String, okActionTitle:String, cancelActionTitle:String, success: (() -> Void)? , cancel: (() -> Void)?)
{
let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertController.Style.actionSheet)
let successAction: UIAlertAction = UIAlertAction(title: okActionTitle, style: .destructive)
{
action -> Void in
success?()
}
let cancelAction: UIAlertAction = UIAlertAction(title: cancelActionTitle, style: .cancel)
{
action -> Void in
cancel?()
}
alert.addAction(successAction)
alert.addAction(cancelAction)
UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true, completion: nil)
}
static func showAlertViewWithTextField(title: String, msg: String, okActionTitle:String, cancelActionTitle:String, success: (() -> Void)? , cancel: (() -> Void)?)
{
let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertController.Style.alert)
alert.addTextField { (textField) in
textField.placeholder = "Enter new pin."
}
alert.addTextField { (textField) in
textField.placeholder = "Confirm new pin."
}
let successAction: UIAlertAction = UIAlertAction(title: okActionTitle, style: .destructive)
{
action -> Void in
let textOfFirstTextfield = alert.textFields?[0].text
print(textOfFirstTextfield)
success?()
}
let cancelAction: UIAlertAction = UIAlertAction(title: cancelActionTitle, style: .cancel)
{
action -> Void in
cancel?()
}
alert.addAction(successAction)
alert.addAction(cancelAction)
UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true, completion: nil)
}
}
it worked when i gave delay while showing hud instead of giving delay while dismissing hud
func makeServiceCall()
{
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1){
Utility.showGlobalProgressHUD(withTitle: "Loading...")
HTTPRequest.serviceReq(newPin: "129354") { (ResetModel) in
Utility.dismissGlobalHUDInMainThread()
Utility.showAlertMessageInMainThread(title: " Reset", msg: "Your request to reset has been successfully completed.")
}
}
}
Related
In Swift, how can I return the string that I write into the UIAlertController's textfield, added if this UIAlertController is inside an extension
Usually if you put your UIAlertController implementation locally in your class, you can easily pass the text, but when the alert is into an extension, I'm not sure which could be the way to return the text.
For example, assume you have this extension:
extension UIViewController {
func presentTextFieldAlert(title: String, message: String, textFieldPlaceholder: String ) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let saveAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default) { _ -> Void in
let urlTextField = alertController.textFields![0] as UITextField
if urlTextField.text != nil { }
}
let cancelAction = UIAlertAction(title: "Cancel", style: .default)
alertController.addTextField { (textField: UITextField!) -> Void in
textField.placeholder = textFieldPlaceholder
}
alertController.addAction(saveAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)
}
}
and into your class:
class Client: UIViewController {
func showAlert() {
self.presentTextFieldAlert(title: "Hello", message: "Write sth", textFieldPlaceholder: "Write here")
}
}
how can I pass the text from the alert to the viewcontroller?
I've tried something like:
class Client: UIViewController {
func showAlert() -> String {
return self.presentTextFieldAlert(title: "Hello", message: "Write sth", textFieldPlaceholder: "Write here")
}
}
but I think it is not the correct way.
Use a completion handler.
extension UIViewController {
func presentTextFieldAlert(title: String, message: String, textFieldPlaceholder: String, completion: #escaping (String?)->()) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let saveAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default) { _ -> Void in
let urlTextField = alertController.textFields![0] as UITextField
completion(urlTextField.text)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .default)
alertController.addTextField { (textField: UITextField!) -> Void in
textField.placeholder = textFieldPlaceholder
completion(nil)
}
alertController.addAction(saveAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)
}
}
Then you can use it as:
class Client: UIViewController {
func showAlert() {
self.presentTextFieldAlert(title: "Hello", message: "Write sth", textFieldPlaceholder: "Write here") { (result) in
if let result = result {
// User entered some text and tapped OK.
}
}
}
}
I created a Utilities class to hold some common functions, one of which is an alertUser function that if called, will display an Alert box to the user with the provided title and message text. In another class file, I am validating some text field entries and if the validation doesn't pass, then I want to use the alertUser function from the Utilities class. However, when I do this, I get the following error message in the Xcode log:
Warning: Attempt to present <UIAlertController: 0x7f9c4be0b140> on <MyAppName.Utilities: 0x7f9c4be1cb60> whose view is not in the window hierarchy!
The calling code is in a UIViewController class file. Here's the code which is in the
class ItemSettingsVC: UIViewController:
private func validateNameField() -> Bool {
var passed = false
if (nameField.hasText) {
passed = true
} else {
Utilities().alertUser(strTitle: "Alert", strMessage: strInvalidNameFieldErrorMsg)
passed = false
}
return passed
}
Here's the alertUser function which is in the
class Utilities: UIViewController:
public func alertUser(strTitle: String, strMessage: String) {
let myAlert = UIAlertController(title: strTitle, message: strMessage, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
myAlert.addAction(okAction)
self.present(myAlert, animated: true, completion: nil)
}
This is running on iOS. I'm using Xcode 8 and swift 3. Any help is greatly appreciated. Thanks.
This should do it:
public func alertUser(strTitle: String, strMessage: String) {
let myAlert = UIAlertController(title: strTitle, message: strMessage, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
myAlert.addAction(okAction)
UIApplication.shared.delegate?.window??.rootViewController?.present(myAlert, animated: true, completion: nil)
}
You have to add an additional parameter in your alertUser function, which would be the VC that will present the alert controller.
for example:
public func alertUser(strTitle: String, strMessage: String, viewController: UIViewController) {
let myAlert = UIAlertController(title: strTitle, message: strMessage, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
myAlert.addAction(okAction)
viewController.present(myAlert, animated: true, completion: nil)
}
But I would recommend that you just make an extension of UIViewController and add your func alertUser()* there because you would surely use this alertUser in different VCs and complexity wise in my opinion, this would be more optimized.
Like this:
extension UIViewController {
func showAlert(title: String, message: String, callback: #escaping () -> ()) {
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: {
alertAction in
callback()
}))
self.present(alert, animated: true, completion: nil)
}
//add additional functions here if necessary
//like a function showing alert with cancel
}
NOTE : Please don't make your Utilities class a subclass of UIViewController, it would also be better to make it a struct handling static functions and/or variables
Use this class for easy to show Alert or ActionSheet
UIAlertController Extension
public extension UIAlertController {
public func showAlert(animated: Bool = true, completionHandler: (() -> Void)? = nil) {
guard let rootVC = UIApplication.shared.keyWindow?.rootViewController else {
return
}
var forefrontVC = rootVC
while let presentedVC = forefrontVC.presentedViewController {
forefrontVC = presentedVC
}
forefrontVC.present(self, animated: animated, completion: completionHandler)
}
}
AppAlert Class Create For UIAlertController Show
public class AppAlert {
private var alertController: UIAlertController
public init(title: String? = nil, message: String? = nil, preferredStyle: UIAlertControllerStyle) {
self.alertController = UIAlertController(title: title, message: message, preferredStyle: preferredStyle)
}
public func setTitle(_ title: String) -> Self {
alertController.title = title
return self
}
public func setMessage(_ message: String) -> Self {
alertController.message = message
return self
}
public func setPopoverPresentationProperties(sourceView: UIView? = nil, sourceRect:CGRect? = nil, barButtonItem: UIBarButtonItem? = nil, permittedArrowDirections: UIPopoverArrowDirection? = nil) -> Self {
if let poc = alertController.popoverPresentationController {
if let view = sourceView {
poc.sourceView = view
}
if let rect = sourceRect {
poc.sourceRect = rect
}
if let item = barButtonItem {
poc.barButtonItem = item
}
if let directions = permittedArrowDirections {
poc.permittedArrowDirections = directions
}
}
return self
}
public func addAction(title: String = "", style: UIAlertActionStyle = .default, handler: #escaping ((UIAlertAction!) -> Void) = { _ in }) -> Self {
alertController.addAction(UIAlertAction(title: title, style: style, handler: handler))
return self
}
public func addTextFieldHandler(_ handler: #escaping ((UITextField!) -> Void) = { _ in }) -> Self {
alertController.addTextField(configurationHandler: handler)
return self
}
public func build() -> UIAlertController {
return alertController
}
}
Used For Open AlertBox
AppAlert(title: "Question", message: "Are you sure?", preferredStyle: .alert)
.addAction(title: "NO", style: .cancel) { _ in
// action
}
.addAction(title: "Okay", style: .default) { _ in
// action
}
.build()
.showAlert(animated: true)
Used For ActionSheet Open
if UIDevice.current.userInterfaceIdiom != .pad {
// Sample to show on iPhone
AppAlert(title: "Question", message: "Are you sure?", preferredStyle: .actionSheet)
.addAction(title: "NO", style: .cancel) {_ in
print("No")
}
.addAction(title: "YES", style: .default) { _ in
print("Yes")
}
.build()
.showAlert(animated: true)
} else {
// Sample to show on iPad
AppAlert(title: "Question", message: "Are you sure?", preferredStyle: .actionSheet)
.addAction(title: "Not Sure", style: .default) {
_ in
print("No")
}
.addAction(title: "YES", style: .default) { _ in
print("Yes")
}
.setPopoverPresentationProperties(sourceView: self, sourceRect: CGRect.init(x: 0, y: 0, width: 100, height: 100), barButtonItem: nil, permittedArrowDirections: .any)
.build()
.showAlert(animated: true)
}
First find out the topmost viewController on your window .
Get the top ViewController in iOS Swift
and then present your alert on that viewController.No need to pass any parameter.
public func alertUser(strTitle: String, strMessage: String) {
let myAlert = UIAlertController(title: strTitle, message: strMessage, preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)
myAlert.addAction(okAction)
topmostVC().present(myAlert, animated: true, completion: nil)
}
I add UICollectionView in my app and each cell has "Delete" trash button.
When I click on this button, it will show alert message to ask. After clicks on OK button, the item in Collection View will delete. However, the UI does not refresh , the item was not deleted.
My Code is ...
override func viewDidLoad() {
super.viewDidLoad()
myCollectionView.reloadData()
}
override func viewDidAppear(_ animated: Bool) {
debugPrint("viewDidAppear")
callWatchLater()
}
override func viewWillAppear(_ animated: Bool) {
DispatchQueue.main.async(execute: {
debugPrint("Appear")
self.myCollectionView.reloadData()
})
}
override func viewDidLayoutSubviews() {
DispatchQueue.main.async(execute: {
debugPrint("SubViews")
self.myCollectionView.reloadData()
})
}
Code for Alert Controller is
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "watchCell", for: indexPath) as! WatchLaterTableCell
let watchTableList = self.watchLaterTable[indexPath.row]
cell.deleteMovie.addTarget(self, action:#selector(showAlert(sender:)), for: .touchUpInside)
}
return cell
}
func showAlert(sender:UIButton!)
{
debugPrint("Press Button")
let alert = UIAlertController(title: "Are you really want to delete this movie?", message: "", preferredStyle: UIAlertControllerStyle.alert)
// Create the actions
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
UIAlertAction in
self.callRest()
debugPrint("Press OK")
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel) {
UIAlertAction in
_ = self.navigationController?.popViewController(animated: true)
}
// Add the actions
alert.addAction(okAction)
alert.addAction(cancelAction)
// Present the controller
DispatchQueue.main.async(execute: {
self.present(alert, animated: true, completion: nil)
})
}
Code For callRest() is
func callRest(){
SwiftLoading().showLoading()
if Reachability().isInternetAvailable() == true {
rest.auth(auth: access_token)
rest.delete(StringResource().mainURL + "user/" + user_id + "/watch/later/" + String(vedioId) , parma: [:], finished: {(result: NSDictionary, status : Int) -> Void in
debugPrint(result)
if(status == 200){
let data = result["data"] as! NSString
self.messages = String(describing: data)
DispatchQueue.main.sync{[unowned self] in
let alertController = UIAlertController(title: "", message: self.messages , preferredStyle: .alert)
// Create the actions
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
UIAlertAction in
debugPrint("call rest Press OK")
self.callWatchLaterGetAPI()
}
alertController.addAction(okAction)
// Present the controller
DispatchQueue.main.async(execute: {
self.present(alertController, animated: true, completion: nil)
})
}
self.myCollectionView.reloadData()
SwiftLoading().hideLoading()
}else{
let error = result["error"] as! NSArray
for item in 0...(error.count) - 1 {
let device : AnyObject = error[item] as AnyObject
self.messages = device["message"] as! String
DispatchQueue.main.sync{[unowned self] in
let alertController = UIAlertController(title: "", message: self.messages , preferredStyle: .alert)
// Create the actions
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
UIAlertAction in
debugPrint("Press OK")
}
alertController.addAction(okAction)
// Present the controller
DispatchQueue.main.async(execute: {
self.present(alertController, animated: true, completion: nil)
})
}
SwiftLoading().hideLoading()
}
}
})
}else{
noInternetConnection()
}
}
However, the CollectionView does not refresh . Can anyone help me this, please?
i find void return alert but string alert return not found.
trying Void to String
// return Void Alert
func returnAlert(title: String!, message: String! ,success: (() -> Void)? , cancel: (() -> Void)?) {
dispatch_async(dispatch_get_main_queue(), {
let alertController = UIAlertController(title:title,
message: "",
preferredStyle: UIAlertControllerStyle.Alert)
self.newQtyField = UITextField()
self.newQtyField.keyboardType = .NumberPad
func addTextField(textField: UITextField!){
// add the text field and make the result global
let row = self.array[Int(message)!]
textField.text = String(row.pbQty!)
self.newQtyField = textField
}
let cancelLocalized = NSLocalizedString("cancel", tableName: "activity", comment:"")
let okLocalized = NSLocalizedString("ok", tableName: "Localizable", comment:"")
let cancelAction: UIAlertAction = UIAlertAction(title: cancelLocalized,
style: .Cancel) {
action -> Void in cancel?()
}
let successAction: UIAlertAction = UIAlertAction(title: okLocalized,
style: .Default) {
action -> Void in success?()
}
alertController.addTextFieldWithConfigurationHandler(addTextField)
alertController.addAction(cancelAction)
alertController.addAction(successAction)
self.presentViewController(alertController, animated: true, completion: nil)
})
}
// bottom call fun | i think success: { () to success: { textfield , but not working how... need your help
returnAlert("title", message: "msg", success: { () -> Void in
})
{ () -> Void in
print("user canceled")
}
Very hard to understand what you are saying in your question.
You should change the method definition to this:
func returnAlert(title: String!, message: String! ,success: ((text:String) -> Void)? , cancel: (() -> Void)?) {
and change the successAction to return the value of the UITextField:
let successAction: UIAlertAction = UIAlertAction(title: okLocalized,
style: .Default) { action in
success?(text: self.newQtyField.text!)
}
I have alert, that write to iOS 8+, I must write same alert to the iOS 7.0 (I'm use four alert's with other request)
There are my code:
func AlertForNumber () {
var alertController: UIAlertController?
//
alertController = UIAlertController(title: "First", message: "Enter number", preferredStyle: .Alert)
alertController!.addTextFieldWithConfigurationHandler({(textField: UITextField!) in
textField.text = "38"
})
let action = UIAlertAction(title: "Next", style: UIAlertActionStyle.Default, handler: {[weak self]
(paramAction: UIAlertAction!) in
if let textFields = alertController?.textFields {
let textFields = textFields as! [UITextField]
let enterText = textFields[0].text
if (count(enterText) < 12){
self?.ErrorForNumber()
} else {
self!.data.numberID = enterText
self!.data.SaveData(enterText, codetext: self!.data.codeID)
self!.json.UfR()
}
}
})
alertController?.addAction(action)
dispatch_async(dispatch_get_main_queue(), {
self.presentViewController(alertController!, animated: true, completion: nil)
})
}
At that alert I must input my number, and send to the server.
I must use only alert with text field
After I must input code at next alert:
func AlertForCode () {
var alertController: UIAlertController?
alertController = UIAlertController(title: "Second", message: "Enter code", preferredStyle: .Alert)
alertController!.addTextFieldWithConfigurationHandler({(textField: UITextField!) in
textField.placeholder = code_text
})
let action = UIAlertAction(title: "Next", style: UIAlertActionStyle.Default, handler: {[weak self]
(paramAction: UIAlertAction!) in
if let textFields = alertController?.textFields {
let textFields = textFields as! [UITextField]
let enterText = textFields[0].text
self!.data.codeID = enterText
self!.data.SaveData(self!.data.numberID, codetext: enterText)
self!.json.UfR()
}
})
alertController?.addAction(action)
dispatch_async(dispatch_get_main_queue(), {
self.presentViewController(alertController!, animated: true, completion: nil)
})
}
So that I must write to the iOS 7.0
func AlertForNumber () {
let alertView = UIAlertView(title: "First", message: "Enter number", delegate: self, cancelButtonTitle: "Next")
alertView.alertViewStyle = UIAlertViewStyle.PlainTextInput
alertView.textFieldAtIndex(0)?.text = "38"
alertView.show()
}
func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) {
println("next")
let enterText = alertView.textFieldAtIndex(0)!.text
if (count(enterText) < 12){
self?.ErrorForNumber()
} else {
self!.data.numberID = enterText
self!.data.SaveData(enterText, codetext: self!.data.codeID)
self!.json.UfR()
}
}