IBAction Btn Not Trigger, [closed] - arrays

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 days ago.
Improve this question
Btn not trigger, I have not ideia what`s happend.
I clicke in the Sebd buton and not happend just not moving, try clean and reset all data all ready but not working!
Thanks for the help!
#IBAction func btnConfirm(_ sender: UIButton!){
var currentRowData = RowData(date: "", tsumiSaki: "", ikisaki: "", yard: "", containerSize: "", fullOrEmpyt: "", containerNumber: "", shyashiNumber: "")
if let dateText = dateField.text, !dateText.isEmpty {
currentRowData.date = dateText
} else {
// show an error message and return early
return
}
if let tsumiSakiText = tsumiSakiField.text {
currentRowData.tsumiSaki = tsumiSakiText
}
if let ikisakiText = ikisakiField.text {
currentRowData.ikisaki = ikisakiText
}
if let yardText = yardTextField.text {
currentRowData.yard = yardText
}
if let containerSizeText = containerSize.text {
currentRowData.containerSize = containerSizeText
}
if let fullOrEmpytText = fullOrEmpytField.text {
currentRowData.fullOrEmpyt = fullOrEmpytText
}
if let containerNumberText = containerNumberField.text {
currentRowData.containerNumber = containerNumberText
}
if let shyashiNumberText = shyashiNumberField.text {
currentRowData.shyashiNumber = shyashiNumberText
}
tableViewData.append(currentRowData.toArray())
clearTextFields()
updateTableView()
saveData()
let alertController = UIAlertController(title: "Input Completed!!", message: "Input Clear", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(okAction)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
Just Trigger the btn and pop data on table view

Related

Firebase and swiftUI, listening for real time update strange behave weird

On my project I'm using firebase Cloud Firestore in order to implement a similar system like "Facebook" to request and confirm friends.
On my app some user are Administrator and some just normal user.
Only normal user can search and add Administrator in order to join some specific event scheduled from the administrator.
here below how is my data in Cloud Firestore :
every user have collection with pending and confirm friends.
I' m using a view to list all the pending and confirm friends for each user
using the .addSnapshotListener {} of firebase I'm checking with the following function every time there is a change on the confirm and pending friend and I publish the change in 2 #Published arrays, pendingFriendsADMIN = [UserMOdel] and confirmedFriendADMIN = [UserMOdel]
func userUpdateFriendUser(userInfo: UserModel){
db.collection("userUser").document(userInfo.email).collection("pendingFriends")
.addSnapshotListener(includeMetadataChanges: false) { documentSnapshot, error in
self.pendingFriendsUSER = []
guard let documents = documentSnapshot?.documents else {
print("Error fetching documents: \(String(describing: error?.localizedDescription))")
return
}
var i = 0
for doc in documents {
debugPrint("inizio il ciclo pending user\(i)")
let idUser = doc["userID"] as? String ?? "no ID"
self.downloadImageForAdmin(userID: idUser) { (urlImage) in
let userPending = UserModel(name: "", surname: "" ,username: "", email: "", userID: "", adminLevel: "", immagine: urlImage!, position: "centro", position2: "sx", vote: 0)
userPending.name = doc["name"] as? String ?? "NA name"
userPending.surname = doc["surname"] as? String ?? "NA surname"
userPending.adminLevel = doc["adminLevel"] as? String ?? "NA admin"
userPending.email = doc["email"] as? String ?? "NA email"
userPending.username = doc["username"] as? String ?? "NA username"
userPending.userID = doc["userID"] as? String ?? "NA id"
userPending.position = doc["position"] as? String ?? "na position"
userPending.position2 = doc["position2"] as? String ?? "na position"
userPending.vote = doc["vote"] as? Int ?? 0
self.pendingFriendsUSER.append(userPending)
i = i+1
debugPrint("finito ciclo pending")
}
}
}
db.collection("userUser").document(userInfo.email).collection("confirmedFriend")
.addSnapshotListener (includeMetadataChanges: false){ documentSnapshot, error in
self.confirmedFriendUSER = []
guard let documents = documentSnapshot?.documents else {
print("Error fetching documents: \(String(describing: error?.localizedDescription))")
return
}
for doc in documents {
debugPrint("inizio il ciclo confirm user \(i)")
let idUser = doc["userID"] as? String ?? "no ID"
self.downloadImageForAdmin(userID: idUser) { (urlImage) in
let userConfirm = UserModel(name: "", surname: "" ,username: "", email: "", userID: "", adminLevel: "", immagine: urlImage!, position: "centro", position2: "sx", vote: 0)
userConfirm.name = doc["name"] as? String ?? "NA name"
userConfirm.surname = doc["surname"] as? String ?? "NA surname"
userConfirm.adminLevel = doc["adminLevel"] as? String ?? "NA admin"
userConfirm.email = doc["email"] as? String ?? "NA email"
userConfirm.username = doc["username"] as? String ?? "NA username"
userConfirm.userID = doc["userID"] as? String ?? "NA id"
userConfirm.position = doc["position"] as? String ?? "na position"
userConfirm.position2 = doc["position2"] as? String ?? "na position"
userConfirm.vote = doc["vote"] as? Int ?? 0
self.confirmedFriendUSER.append(userConfirm)
}
}
}
}
the similar method is used also for listed the change on the userFriendList.
a user, can search an administrator via the email, and send to him a friend request(see below)
the user sent the friend request with the following function:
simply, I write on the pending friend the of the user the admin email and in the admin pending friend the user email
func sendFriendRequest(userInfo: UserModel, userToRequest: UserModel, closure: #escaping warning){
// check if reuqest already sent
self.db.collection("userAdmin").document(userToRequest.email).collection("confirmedFriend").whereField("email", isEqualTo: userInfo.email).getDocuments() { (queryResult, err) in
if let err = err {
debugPrint("unable to get data , friend alrady request\(err)")
} else {
if queryResult!.documents.count > 0 {
debugPrint("siete gia amici") // mettere warning
let warning = true
closure(warning)
return
} else {
// if request never sent, metto user nella lista dell admin pending
self.db.collection("userAdmin").document(userToRequest.email).collection("pendingFriends").document(userInfo.email).setData([
"username": userInfo.username,
"email" : userInfo.email,
"userID" : userInfo.userID,
"adminLevel": userInfo.adminLevel,
"name":userInfo.name,
"surname":userInfo.surname,
"position": userInfo.position,
"position2": userInfo.position2,
"vote": userInfo.vote
], merge: false) { (err) in
self.db.collection("userUser").document(userInfo.email).collection("pendingFriends").document(userToRequest.email).setData([
"username": userToRequest.username,
"email" : userToRequest.email,
"userID" : userToRequest.userID,
"adminLevel": userToRequest.adminLevel,
"name":userToRequest.name,
"surname":userToRequest.surname,
"position": userToRequest.position,
"position2": userToRequest.position2,
"vote": userToRequest.vote
], merge: false)
}
// metto sulla mia pending request
}
}
}
}
Here the problem...
some time , not always once I sent the request to a friend admin the .addSnapshotListener duplicate the change , as you can se from the third picture there is 2 time the same pending friend.
If I exit from the view and I go back the pending friend are correct.
here the code of my AdminFriendRequest : View
import SwiftUI
import URLImage
struct AdminFriendRequest: View {
#Binding var dismissView : Bool
#ObservedObject var dm : DataManager
#Binding var meInfo: UserModel?
var body: some View {
VStack{
fakebar
Spacer()
List{
HStack {
Image(systemName: "person.2")
Text("Pending friends request:")
}.font(.headline)
.foregroundColor(.blue)
ForEach(dm.pendingFriendsADMIN) { friend in
HStack{
if friend.immagine == nil{
Image(systemName: "person")
.resizable()
.frame(width: 30, height: 30, alignment: .center)
.clipShape(Circle())
} else {
URLImage(friend.immagine!) { proxy in
proxy.image
.resizable()
.frame(width: 30, height: 30, alignment: .center)
.clipShape(Circle())
}
}
Text(friend.username)
Spacer()
Image(systemName: "checkmark.circle")
}
.onTapGesture {
if self.meInfo != nil {
self.dm.tapToConfirmFriend(me: self.meInfo!, friendToConfirm: friend) { (isFriendConfirm) in
debugPrint("is friend confirm \(isFriendConfirm)")
}
}
}
}
if dm.pendingFriendsADMIN.isEmpty {
Text("No friend request yet").font(.caption)
}
HStack {
Image(systemName: "person.3")
Text("Friends:")
}.font(.headline)
.foregroundColor(.blue)
ForEach(dm.confirmedFriendADMIN) { friend in
HStack{
if friend.immagine == nil{
Image(systemName: "person")
.resizable()
.frame(width: 30, height: 30, alignment: .center)
.clipShape(Circle())
} else {
URLImage(friend.immagine!) { proxy in
proxy.image
.resizable()
.frame(width: 30, height: 30, alignment: .center)
.clipShape(Circle())
}
}
Text(friend.username)
Spacer()
Image(systemName: "checkmark.circle").foregroundColor(.green)
Button(action: {
self.dm.removeFriend(me: self.meInfo!, friendConfirm: friend)
}, label: {
Text("remove friend")
})
}.padding(.all)
}
}.padding(.trailing)
}
.onAppear {
self.dm.newListUpdateForAdmin(userInfo: self.meInfo!)
}
}
var fakebar: some View {
ZStack {
HStack {
Spacer()
Image(systemName: "chevron.compact.down")
.font(.system(size: 60))
.aspectRatio(contentMode: .fit)
.foregroundColor(.white)
Spacer()
}
HStack {
Spacer()
Button(action: {
self.dismissView.toggle()
}) {
Text("Close")
.fontWeight(.bold)
.foregroundColor(.white)
.padding(.horizontal)
}
}
}
.frame(height: 44)
.background(Color.green.padding(.top, -44))
}
}
I use the onAppear to trigger the list update with the .addSnapshotListener
.onAppear {
self.dm.newListUpdateForAdmin(userInfo: self.meInfo!)
}
I can't find out why... is it correct the way how i'm using the .addSnapshotListener ?
Or any other idea how to handle the friend request. happy to change my way how to deal with the friend request.
Thanks
Some suggestions that maybe helps:
1. Implement listener state control: These help to control when a user add, modify or remove a record, helps not to reload all data and allow not to duplicate events, for example in the code below I get all users (event documentChange.add) if a new user is added you don't reload all users array.
Api:
function getUsersPending(userInfo: UserModel, onSuccess: #escaping([UserModel]) -> Void, onError: #escaping(_ errorMessage: String) -> Void, newPendingUser: #escaping(UserModel) -> Void ) {
db.collection("userUser").document(userInfo.email).collection("pendingFriends").addSnapshotListener(includeMetadataChanges: false) { documentSnapshot, error in
self.pendingFriendsUSER = []
guard let snapshot = documentSnapshot else { return }
var userPendingArray = [UserModel]()
snapshot.documentChanges.forEach { (documentChange) in
switch documentChange.type {
case: .added :
let dict = documentChange.document.data()
//Get User from firebase doc pendingUser = ....
newPendingUser(pendingUser) //escape New User
userPendingArray.appen(pendingUser)
print("Pending User Added")
case .modified :
//implements action (new escaping)
print("Pending User Modified")
case .removed :
print("User pending removed")
}
}
onSuccess(userPendingArray)
}
Users pending ViewModel sample
class UserPendingViewModel() : ObservableObject {
#Published var usersPending: [UserModel] = []
#Published var isLoading = false
var errorString : String = ""
func loadUsersPending() {
self.usersPending = []
self.isLoading = true
dm. getUsersPending(userInfo: userModel, onSuccess: { (users) in
if (self.usersPending.isEmpty) { self.usersPending = users }
self.isLoading = false
}, onError: { (errorMessage) in
print("Error Message \(errorMessage)")
}, newPendingUser: { (user) in
if (!self.usersPending.isEmpty) { self.usersPending.append(user) }
})
}
}
View
struct UserPendingView: View {
#ObservedObject var model = UserPendingViewModel()
var body: some View {
ScrollView {
if !model.usersPending.isEmpty {
ForEach(model.usersPending, id: \.messageId) { user in
//Show your data
}
}
}.onAppear{ self.model.loadUsersPending() }
}
2. Activate / Deactivate listeners. If your app is not showing the pending view users no need to keep alive listeners. Activate the listener onAppear and Deactivate onDisappear.
On previous sample New escaping, var listener declaration and result on Api
function getUsersPending(userInfo: UserModel, onSuccess: #escaping([UserModel]) -> Void, onError: #escaping(_ errorMessage: String) -> Void, newPendingUser: #escaping(UserModel) -> Void, listener: #escaping(_ listenerHandle: ListenerRegistration) -> Void ) { ) {
let listenerRegistration = db.collection("userUser").document(userInfo.email).collection("pendingFriends").addSnapshotListener(includeMetadataChanges: false) { documentSnapshot, error in
self.pendingFriendsUSER = []
guard let snapshot = documentSnapshot else { return }
var userPendingArray = [UserModel]()
snapshot.documentChanges.forEach { (documentChange) in
switch documentChange.type {
case: .added :
let dict = documentChange.document.data()
//Get User from firebase doc pendingUser = ....
newPendingUser(pendingUser) //escape New User
userPendingArray.appen(pendingUser)
print("Pending User Added")
case .modified :
//implements action (new escaping)
print("Pending User Modified")
case .removed :
print("User pending removed")
}
}
onSuccess(userPendingArray)
}
listener(listenerRegistration) //escaping listener
}
Users pending ViewModel sample, declaration listener and add function listener result (Note: import Firebase)
class UserPendingViewModel() : ObservableObject {
#Published var usersPending: [UserModel] = []
#Published var isLoading = false
var errorString : String = ""
var listener : ListenerRegistration!
func loadUsersPending() {
self.usersPending = []
self.isLoading = true
dm. getUsersPending(userInfo: userModel, onSuccess: { (users) in
if (self.usersPending.isEmpty) { self.usersPending = users }
self.isLoading = false
}, onError: { (errorMessage) in
print("Error Message \(errorMessage)")
}, newPendingUser: { (user) in
if (!self.usersPending.isEmpty) { self.usersPending.append(user) }
}) { (listener) in
self.listener = listener
}
}
}
View implement onDisappear to disconnect listener
struct UserPendingView: View {
#ObservedObject var model = UserPendingViewModel()
var body: some View {
ScrollView {
if !model.usersPending.isEmpty {
ForEach(model.usersPending, id: \.messageId) { user in
//Show your data
}
}
}.onAppear{ self.model.loadUsersPending() }
.onDisappear {
if self.model.listener != nil {
self.model.listener.remove()
}
}
}

Instance method 'contains' requires that 'UITextField' conform to 'StringProtocol'

I have a tableview that displays a sourceArray with a Name and Category properties. I want to filter the Category property of the sourceArray based on the users input from a UIAlertController but getting the error "Instance method 'contains' requires that 'UITextField' conform to 'StringProtocol'". Any help is greatly appreciated.
var sourceArray = [(Name: String, Category: String, Picture1: UIImage, Picture2: UIImage, Picture3: UIImage, Description: String)]()
#IBAction func filterButton(_ sender: UIBarButtonItem) {
var textField = UITextField()
let alert = UIAlertController(title: "Category", message: nil, preferredStyle: .alert)
let action = UIAlertAction(title: "Filter", style: .default) { (action) in
print(textField)
let filtered = sourceArray.filter({$0.Category.contains(textField)})
self.filteredArray = filteredArray.isEmpty ? sourceArray : filtered
self.tableview.reloadData()
}
alert.addTextField { (alertTextField) in
alertTextField.placeholder = "Biceps, Chest, Shoulders, etc."
textField = alertTextField
}
alert.addAction(action)
present(alert, animated: true, completion: nil)
}
This issue I was having is that textField was not being recognized as a String. So I added a constant text as a String and assigned the textField.text to it like so.
#IBAction func filterButton(_ sender: UIBarButtonItem) {
var textField = UITextField()
let alert = UIAlertController(title: "Category", message: nil, preferredStyle: .alert)
let action = UIAlertAction(title: "Filter", style: .default) { (action) in
let text: String = textField.text!
let filtered = self.sourceArray.filter({$0.Category.contains(text)})
self.filteredArray = self.filteredArray.isEmpty ? self.sourceArray : filtered
self.tableview.reloadData()
}
alert.addTextField { (alertTextField) in
alertTextField.placeholder = "Biceps, Chest, Shoulders, etc."
textField = alertTextField
}
alert.addAction(action)
present(alert, animated: true, completion: nil)
}

Sending an email with a loop as body in Swift

I would like to send an email with different steps and values depending on what the user has edited on an image. For that, I'm using UserDefaults to save values.
Then I have the next code into an UIAlertController:
alert.addAction(UIAlertAction(title: "Send", style: .default)
{ action -> Void in
//i is the last step register
let nombre = alert.textFields![0]
for n in 1...self.i {
print("Step \(n): \(self.filterUserDefaults.string(forKey: "Step_\(n)")!)")
}
let filters = [
"Brillo",
"Exposicion",
"Contraste",
"Saturacion",
"Saturacion_color",
"Temperatura",
"Blanco_Negro",
"HUE",
"Tintado_Rojo",
"Tintado_Rosa",
"Tintado_Naranja",
"Tintado_Amarillo",
"Tintado_Purpura",
"Tintado_Verde",
"Tintado_Azul",
"Tintado_Marron",
"Tintado_Gris"]
for filter in filters {
print("\(filter) = \(self.filterUserDefaults.float(forKey: filter).roundTo(places: 3))")
}
self.sendMail(filtro: nombre.text!, body: "XXXX")
})
present(alert, animated: true)
}
func sendMail(filtro: String, body: String) {
if MFMailComposeViewController.canSendMail() {
let mail = MFMailComposeViewController()
mail.mailComposeDelegate = self
mail.setToRecipients(["blablabla#gmail.com"])
mail.setSubject("Filtro \(filtro)")
mail.setMessageBody(body, isHTML: true)
present(mail, animated: true)
} else {
print("Error presenting email app.")
}
}
So printing is working as I expect but the problem is to put these prints into the body of sendMail function...
I tried:
var steps: [String]?
for n in 1...self.i {
steps = ["Step \(n): \(self.filterUserDefaults.string(forKey: "Step_\(n)")!)"]
}
.
.
.
self.sendMail(filtro: nombre.text!, body: steps!.joined(separator: "\n"))
But only the last step is written into the body's email and not the array...
Please, can anyone help me?
Thank you in advance!
u can try out following code
var steps: String = ""
for n in 1...self.i {
steps += "Step \(n): \(self.filterUserDefaults.string(forKey: "Step_\(n)")!)"
}
You are almost there, you need to initialise your array variable and use append
var steps = [String]()
for n in 1...self.i {
steps.append("Step \(n): \(self.filterUserDefaults.string(forKey: "Step_\(n)")!)")
}
...
self.sendMail(filtro: nombre.text!, body: steps.joined(separator: "\n"))

In-App purchase restore button restores non purchased In-Apps

I am very lost when it comes to in app purchases. I found a very solid post on stack overflow that has been helpful. [Stack Post][1] I am still having issues after this though. If I have an in app purchase thats never been bought before and I tap the restore button it will unlock it anyway. Any help would be amazing thanks.
class ViewController: UIViewController, SKProductsRequestDelegate, SKPaymentTransactionObserver {
#IBOutlet weak var nonConsumableLabel: UILabel!
let id_sold = "id_sold"
var productID = ""
var productsRequest = SKProductsRequest()
var iapProducts = [SKProduct]()
var nonConsumablePurchaseMade = UserDefaults.standard.bool(forKey: "nonConsumablePurchaseMade")
override func viewDidLoad() {
super.viewDidLoad()
// Check your In-App Purchases
print("NON CONSUMABLE PURCHASE MADE: \(nonConsumablePurchaseMade)")
if nonConsumablePurchaseMade { nonConsumableLabel.text = "Premium version PURCHASED!"
} else { nonConsumableLabel.text = "Premium version LOCKED!"}
// Fetch IAP Products available
fetchAvailableProducts()
}
#IBAction func nonConsumableBtn(_ sender: Any) {
purchaseMyProduct(product: iapProducts[0])
}
#IBAction func printer(_ sender: Any) {
print(iapProducts)
}
// MARK: - RESTORE NON-CONSUMABLE PURCHASE BUTTON
#IBAction func restorePurchaseButt(_ sender: Any) {
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().restoreCompletedTransactions()
}
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
nonConsumablePurchaseMade = true
UserDefaults.standard.set(nonConsumablePurchaseMade, forKey: "nonConsumablePurchaseMade")
let alert = UIAlertController(title: "IAP Tutorial", message: "You've successfully restored your purchase!", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Close", style: .cancel, handler: nil))
self.present(alert, animated: true)
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
for transaction in queue.transactions {
let t: SKPaymentTransaction = transaction
let prodID = t.payment.productIdentifier as String
switch prodID {
case "id_sold":
// implement the given in-app purchase as if it were bought
print("Second IAP restored")
default:
print("iap not found")
}
}
}
}
// MARK: - FETCH AVAILABLE IAP PRODUCTS
func fetchAvailableProducts() {
// Put here your IAP Products ID's
let productIdentifiers = NSSet(objects:
id_sold
)
productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set<String>)
productsRequest.delegate = self
productsRequest.start()
}
// MARK: - REQUEST IAP PRODUCTS
func productsRequest (_ request:SKProductsRequest, didReceive response:SKProductsResponse) {
if (response.products.count > 0) {
iapProducts = response.products
// Get its price from iTunes Connect
let numberFormatter = NumberFormatter()
numberFormatter.formatterBehavior = .behavior10_4
numberFormatter.numberStyle = .currency
// 2nd IAP Product (Non-Consumable) ------------------------------
let secondProd = response.products[0] as SKProduct
// Get its price from iTunes Connect
numberFormatter.locale = secondProd.priceLocale
}
}
// MARK: - MAKE PURCHASE OF A PRODUCT
func canMakePurchases() -> Bool { return SKPaymentQueue.canMakePayments() }
func purchaseMyProduct(product: SKProduct) {
if self.canMakePurchases() {
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().add(payment)
print("PRODUCT TO PURCHASE: \(product.productIdentifier)")
productID = product.productIdentifier
// IAP Purchases dsabled on the Device
} else {
let alert = UIAlertController(title: "IAP Tutorial", message: "You've successfully restored your purchase!", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Close", style: .cancel, handler: nil))
self.present(alert, animated: true)
}
}
// MARK:- IAP PAYMENT QUEUE
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction:AnyObject in transactions {
if let trans = transaction as? SKPaymentTransaction {
switch trans.transactionState {
case .purchased:
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
if productID == id_sold {
// Save your purchase locally (needed only for Non-Consumable IAP)
nonConsumablePurchaseMade = true
UserDefaults.standard.set(nonConsumablePurchaseMade, forKey: "nonConsumablePurchaseMade")
nonConsumableLabel.text = "Premium version PURCHASED!"
let alert = UIAlertController(title: "IAP Tutorial", message: "You've successfully unlocked the Premium version!", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Close", style: .cancel, handler: nil))
self.present(alert, animated: true)
}
break
case .failed:
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
break
case .restored:
SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
break
default: break
}
}
}
}
You are saying
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
nonConsumablePurchaseMade = true
UserDefaults.standard.set(nonConsumablePurchaseMade, forKey: "nonConsumablePurchaseMade")
}
But that method is called even if nothing was restored. All it means is that the restoration interaction is over, not that it succeeded. But you are going ahead and acting as if it succeeded, and awarding your user the magic user defaults key.

Passing global Arrays through functions is not working in swift

I have this program which takes values from firestore and puts them in an array. I have confirmed that these arrays have data inside of them by using test print functions. When I declare 2 global arrays ( gloabalGPA and globalSAT) and pass the value of the gpaColleges and the satColleges into them through a function everything works. I placed test print functions inside of the functions (the swithcSATArray and the switchGPAArray). However when I attempt to print these global variables again in a different function the print function prints out an empty array. like so: ( [] )
import UIKit
import FirebaseAuth
import FirebaseDatabase
import Firebase
import FirebaseFirestore
class ScoresViewController: UIViewController {
var docRef: DocumentReference!
let defaultStore = Firestore.firestore()
var globalGPA = [String]()
var globalSAT = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let userID: String = (Auth.auth().currentUser?.uid)!
docRef = Firestore.firestore().document("Users/\(userID)")
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBOutlet weak var GpaScore: UITextField!
#IBOutlet weak var SATscore: UITextField!
#IBOutlet weak var ACT_Score: UITextField!
#IBAction func SubmitTapped(_ sender: Any) {
print("Submit Tapped")
let Sattext = SATscore.text
let Acttext = ACT_Score.text
let Gpatext = GpaScore.text
let gpaScore = Gpatext
let SatScore2 = Sattext
let Acttext2 = Acttext
let CombinedScores = Sattext! + Acttext!
if GpaScore.text == "" {
self.createAlert(titleText: "Error", messageText: "No Weighted GPA Entered")
}
else if CombinedScores == "" {
self.createAlert(titleText: "Error", messageText: "No SAT nor ACT Score Entered")
}
else{
let dataToSave: [String: Any] = ["GPA": gpaScore!, "SAT Score": SatScore2!, "ACT Score": Acttext2!]
docRef.setData(dataToSave) { (error) in
if let error = error {
print("error in sending data to fireStore: \(error.localizedDescription)")
}else {
print("Data was succesfully saved to FireStore")
}
}
self.presentLoggedInScreen()
sendToFireStore(gpa: gpaScore!, sat: SatScore2!)
self.addArrays()
}
}
func createAlert (titleText : String , messageText: String) {
let alert = UIAlertController (title: titleText, message: messageText, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Dissmis", style: .default, handler: { (action) in alert.dismiss(animated: true, completion: nil)
}))
self.present(alert, animated: true, completion: nil)
}
func presentLoggedInScreen() {
let storyboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let HomeVC:HomeVC = storyboard.instantiateViewController(withIdentifier: "HomeVC") as! HomeVC
self.present(HomeVC, animated: true, completion: nil)
}
func sendToFireStore(gpa: String, sat: String) {
let db = Firestore.firestore()
var gpaColleges = [String]()
let gpaRef = db.collection("Colleges")
let query1 = gpaRef
.whereField("Average GPA", isLessThanOrEqualTo: gpa)
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
gpaColleges.append(document.documentID)
}
self.switchGPAArray(gpa: gpaColleges)
}
}
var satColleges = [String]()
let satRef = db.collection("Colleges")
let query2 = satRef
.whereField("Average SAT Score", isLessThanOrEqualTo: sat)
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
satColleges.append(document.documentID)
}
self.swithcSATArray(sat: satColleges)
}
}
}
func swithcSATArray(sat: Array<Any>) {
self.globalSAT = sat as! [String]
print("Printing inside of SAT function \(self.globalSAT)")
}
func switchGPAArray(gpa: Array<Any>) {
self.globalGPA = gpa as! [String]
print("Printing inside of GPA funtion \(self.globalGPA)")
}
func addArrays() {
print("INSIDE OF ADD ARRAYS SAT \(self.globalSAT)")
print("INSIDE OF ADD ARRAYS GPA \(self.globalSAT)")
}
}
Any help would be greatly appreciated.
First of all there is lot of code but little information about your problem. We don't even know which function you call first and what is the second one that prints empty?
I can edit this answer after you provide more details. But as far as I see, you have closures and the compiler won't wait closure to complete, to run the next line. If this is the problem you can use threads and run your code in main thread so you can be sure it is completed. Or you can use delegate pattern to be notified when it's complete.
Or just do this:
let dataToSave: [String: Any] = ["GPA": gpaScore!, "SAT Score": SatScore2!, "ACT Score": Acttext2!]
docRef.setData(dataToSave) { (error) in
if let error = error {
print("error in sending data to fireStore: \(error.localizedDescription)")
}else {
self.presentLoggedInScreen()
sendToFireStore(gpa: gpaScore!, sat: SatScore2!)
self.addArrays()
print("Data was succesfully saved to FireStore")
}
}
If no one above works, provide more details about your issue! :)

Resources