IPv6 Crash Firebase Swift - swift

I have a Swift app using Firebase as backend.
It works perfectly fine on all simulators and my own iOS devices, but when I submitted it to Apple for review, it crashed specifically when the reviewer tapped on a UIButton that presents a UIAlertController containing my content reporting mechanism:
#IBAction func moreActions(_ sender: AnyObject) {
// 1
let optionMenu = UIAlertController(title: nil, message: "Choose Action", preferredStyle: .actionSheet)
// 2
let reportPost = UIAlertAction(title: "Report this post", style: .default, handler: {
(alert: UIAlertAction!) -> Void in
self.report()
})
// 3
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {
(alert: UIAlertAction!) -> Void in
print("Cancelled")
})
// 4
optionMenu.addAction(reportPost)
optionMenu.addAction(cancelAction)
self.present(optionMenu, animated: true, completion: nil)
}
func report() {
let messageView = MessageView.viewFromNib(layout: .CardView)
var config = SwiftMessages.Config()
config.dimMode = .gray(interactive: true)
messageView.configureTheme(.info)
messageView.button?.isHidden = true
messageView.configureContent(title: "Thank you", body: "We have received your report, and will soon make all necessary actions.")
SwiftMessages.show(config: config, view: messageView)
ref = FIRDatabase.database().reference()
ref.child("reportedPost").observeSingleEvent(of: .value, with: {(snapshot) in
if snapshot.hasChild(self.passedPurchaseKey) {
print("this post has been reported before")
let targetKey = self.passedPurchaseKey
let value = snapshot.childSnapshot(forPath: targetKey!).value as! Int
let newValue = value + 1
self.ref.child("reportedPost").updateChildValues([targetKey!: newValue])
}else{
print("this post has not been reported before")
let targetKey = self.passedPurchaseKey
self.ref.child("reportedPost").updateChildValues([targetKey!: 1])
}
})
}
The reviewer suggested that the crash might due to IPv6 incompatibility. I cannot agree with them since the networking logics above are very similar to the rest of my App, which did not lead to any crashes. Thus I suspect that the crash was due to something else.
Yet I could not be sure because I do not have the required hardwares to test my app under IPv6 environment.
Thanks in advance for your kind help!
//edit 1: crash log added
crashlog_1
crashlog_2

Related

UIAlertController not getting deallocated

I have created a UIAlertController and added a text field into it. The problem is that the after I dismiss the alertcontroller, it is not deallocating and shows in the memory graph.
let alertController = UIAlertController(title: "Enter link", message: nil, preferredStyle: .alert)
alertController.addTextField { (textField) in
textField.placeholder = "www.xxx.com"
}
let cancel = UIAlertAction(title: "CANCEL", style: .cancel, handler: nil)
let ok = UIAlertAction(title: "SUBMIT", style: .default) { [weak self] (_) in
guard let self = self else { return }
guard let textFields = alertController.textFields, let textField = textFields.first else { return }
if let text = textField.text {
}
}
alertController.addAction(cancel)
alertController.addAction(ok)
present(alertController, animated: true, completion: nil)
However, if I remove the alertController.addTextField then it gets deallocated and it does not exist in the memory graph.
I tried checking if there are any memory leaks introduced due to my code but found none.
You're retaining the alertController inside of "ok" alert action, which is in turn retained by UIAlertController.
That's a retain cycle, neither of objects will be able to release each other.
You should avoid that, perhaps by using a weak reference, i.e:
let ok = UIAlertAction(title: "SUBMIT", style: .default) { [weak alertController] (_) in
// Upgrade weak to strong reference
guard let alertController = alertController else { return }
// Do your thing
}

Code not finishing the function, it is ending execution halfway through

My code is as follows:
#IBAction func clicked(_ sender: Any) {
let ref = Database.database().reference()
let pass = password.text
var firpass = ""
var bool = false;
ref.child(name.text as! String).child("password").observeSingleEvent(of: .value, with: { dataSnapshot in
firpass = dataSnapshot.value as! String
if firpass == pass {
bool = true
print("in here")
}
})
print(bool)
if bool {
self.sendname = name.text!
let vc = DatabaseTableViewController(nibName: "DatabaseTableViewController", bundle: nil)
vc.finalName = self.sendname
navigationController?.pushViewController(vc, animated: true)
performSegue(withIdentifier: "username", sender: self)
} else {
let alert = UIAlertController(title: "Error", message: "Incorrect username or password", preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
"in here" gets printed, but bool is never printed and the alert is showing. Why does my code not enter the if bool block and output the alert?
Data is loaded from Firebase asynchronously, since it may take a while. Instead of making your app wait for the data (which would be a bad user experience), your main code continues while the data is being loaded, and then once the data is available your closure is called.
This explains the behavior you're seeing: by the time your runs, the hasn't run yet.
the solution is as simple as it is initially confusing and annoying: any code that needs the data from the database must be inside the closure, or be called from there.
So for example:
ref.child(name.text as! String).child("password").observeSingleEvent(of: .value, with: { dataSnapshot in
firpass = dataSnapshot.value as! String
if firpass == pass {
bool = true
print("in here")
}
print(bool)
if bool {
self.sendname = name.text!
let vc = DatabaseTableViewController(nibName: "DatabaseTableViewController", bundle: nil)
vc.finalName = self.sendname
navigationController?.pushViewController(vc, animated: true)
performSegue(withIdentifier: "username", sender: self)
} else {
let alert = UIAlertController(title: "Error", message: "Incorrect username or password", preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
})
Also see:
Firebase with Swift 3 counting the number of children
Array of struct not updating outside the closure
getting data out of a closure that retrieves data from firebase (showing examples with custom callbacks and delegates)
How to reload data after all Firebase calls finished? (showing how to use a dispatch group)
Finish all asynchronous requests before loading data? (another example using a dispatch group)
Also you have to set variable bool to false when you are navigating to next view controller after login. So that you login again and if password is wrong then you can not navigate to next page and only it shows alert for wrong password.

Link to Facebook from IOS app

I'm trying to make a link to our business facebook page from my app. So far it doesn't seem to be working. My aim was to click a button 'Facebook', have an alert pop up asking if the person wanted to open Facebook with a yes/cancel answer, and then refer them directly to our Facebook page either in the app or on the web. I've tried searching and everything I'm finding doesn't seem to help me with exactly what I needed to I tried to incorporate my own button with a link to the page I want but I don't seem to be getting anywhere. When I run my app in the simulator, the button is functional in so much as it presses and highlights but doesn't provide the alert which should then allow the person to go to the Facebook page.
Can someone help me achieve this. So far this is what I have:
#IBAction func displayFacebookPage(_ sender: Any) {
let alert = UIAlertController(title: "Open in Facebok?", message: nil, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.default) {_ in
let appURL = URL(string: "fb:/
let webURL = URL(string: "https:/
let application = UIApplication.shared
if application.canOpenURL(appURL) {
if #available(iOS 10.0, *) {
application.open(appURL)
} else {
if #available(iOS 10.0, *) {
application.open(webURL as URL)
} else {
}
}
alert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
}
Thanks!
Your braces are not correct. Use the following code
let alert = UIAlertController(title: "Open in Facebok?", message: nil, preferredStyle: UIAlertControllerStyle.alert)
let action = UIAlertAction(title: "Yes", style: UIAlertActionStyle.default) { _ in
let appURL = URL(string: "fb:/")
let webURL = URL(string: "https:/")
let application = UIApplication.shared
if application.canOpenURL(appURL!) {
if #available(iOS 10.0, *) {
application.open(appURL!)
} else {
if #available(iOS 10.0, *) {
application.open(webURL!)
} else {
}
}
}
}
let noAction = UIAlertAction(title: "No", style: UIAlertActionStyle.cancel, handler: nil)
alert.addAction(action)
alert.addAction(noAction)
self.present(alert, animated: true, completion: nil)

AWS Cognito doesn't call confirmSignUp when confirming user identity in Swift with Xcode

I finally managed to get the SignUp to work, but when trying to confirm the signup, I'm reaching a problem. Here is my code:
var user: AWSCognitoIdentityUser?
#IBAction func submitButton(_ sender: Any) {
guard let confirmationCodeValue = self.codeTextField.text, !confirmationCodeValue.isEmpty else {
let confirmationAlert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert)
confirmationAlert.addAction(UIAlertAction(title: "好", style: .default, handler: {action in
print("Try again!")
}))
self.present(confirmationAlert, animated: true, completion: nil)
return
}
self.user?.confirmSignUp(self.codeTextField.text!, forceAliasCreation: true).continue({[weak self] (task: AWSTask) -> Any? in
guard let strongSelf = self else { return nil }
DispatchQueue.main.async(execute: {
print("At least this is working...")
if let error = task.error {
let confirmationFailAlert = UIAlertController(title: (error as NSError).userInfo["__type"] as? String,
message: (error as NSError).userInfo["__type"] as? String,
preferredStyle: .alert)
confirmationFailAlert.addAction(UIAlertAction(title: "好",
style: .default,
handler: {action in
}))
self?.present(confirmationFailAlert, animated: true, completion: nil)
} else {
let confirmationSuccessAlert = UIAlertController(title: self?.alertTitleConfirmationComplete,
message:self?.alertMessageConfirmationComplete,
preferredStyle: .alert)
confirmationSuccessAlert.addAction(UIAlertAction(title: "好",
style: .default,
handler: {action in
self?.dismiss(animated: true, completion: nil)
}))
self?.present(confirmationSuccessAlert, animated: true, completion: nil)
}
})
return nil
})
}
The first part of this code works fine. If I type nothing in the space, I get an alertView telling me so. However, if I type anything in the space, nothing happens. The print statement "At least this is working..." never gets called. I've been staring at this code for a couple hours now trying to figure out what's wrong, and I feel like it's probably something simple, but as of now, I could use some help!
Thanks in advance!
I assume the code block above is not the full source, but be sure the optional, user, is "unencapsulated" and equal to an actual instance of AWSCognitoIdentityUser.
If it isn't, which I am assuming it is not, confirmSignUp won't know the username, sub, or have any information on the user it is "confirming".
I would recommend logging user and be sure that username is in fact a value within user.
I believe you set it equal to that instance type in the response to your AWSCognitoIdentityUserPool class signUp:password:userAttributes:validationData: call.
Check those values that are returned in AWSCognitoIdentityUserPoolSignUpResponse.

Why can't won't the MFMailComposerViewController be dismissed?

Whenever I press "Cancel" then "Delete Draft", the mail composer won't be dismissed. The error I'm getting is "Thread 1: EXC_BAD_ACCESS (code=1, address=0x40363380)"
In my TableViewController I have:
#IBAction func mailButton(sender: AnyObject) {
let emailComposer = EmailComposer()
if email != "" {
print(email)
if emailComposer.canSendMail() {
emailComposer.setRecipient(email)
let configuredMailComposeViewController = emailComposer.configuredMailComposeViewController()
presentViewController(configuredMailComposeViewController, animated: true, completion: nil)
}
} else {
let alertController = UIAlertController(title: "Sorry!", message: "No email found for this contact", preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title: "OK", style: .Default, handler: { (action) -> Void in
//do nothing
}))
self.presentViewController(alertController, animated: true, completion:nil)
}
}
For those who don't know, EXC_BAD_ACCESS means its trying to access something in memory that is no longer there. I wrongfully created the EmailComposer() object after the button tap so it was going out of scope. So this:
let emailComposer = EmailComposer()
...should have been created here, for example:
class TableViewController: UITableViewController {
let emailComposer = EmailComposer()