swift4 creating users info name, age and getting data back from fire base - swift

I have created firebase all good with sign in and signup I can
store images as well but can't get images back that are stored in firebase and I want to create user profile to store name and age of user,
success with login, storing image with firebase and have created real time data base child such as image user name and age but cant use in my app, issue in creating user profile and issue with getting image back from firebase storage.
import UIKit
import FirebaseAuth
import Firebase
import FirebaseStorage
class ViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate {
var ref : DatabaseReference?
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var myImage: UIImageView!
#IBOutlet weak var userName: UITextField!
#IBOutlet weak var ageTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// get image from firebase
// imagesFolder.
// let imageBack = Database.database().reference().child("images").child("user")
// self.myImage.image = UIImage(data: data!)
// creating dataBase
ref = Database.database().reference()
if Auth.auth().currentUser != nil {
ref?.child("images").child("username").setValue(["name":"first", "age":28])
}
}
#IBAction func loginButtonPressed(_ sender: UIButton) {
}
// signUp Button pressed
#IBAction func signUpButtonPressed(_ sender: UIButton) {
Auth.auth() .createUser(withEmail: emailTextField!.text!, password: passwordTextField!.text!) {(user,error)
in
if user != nil
{
self.performSegue(withIdentifier: "goToHome", sender: self)
print("SignUp Sucessfull")
}
else {
print("unSucessfull")
// uiAlert
let alert = UIAlertController(title:"wrong Information", message: nil, preferredStyle: .alert)
let okButton = UIAlertAction(title: "ok", style: .default, handler: nil)
alert.addAction(okButton)
self.present(alert,animated: true,completion: nil)
print("login Failed")
}
guard let userName = self.userName.text,!userName.isEmpty else {
print("Email is Empty");return
}
guard let userAge = self.ageTextField.text,!userAge.isEmpty else {
print("Age is required"); return
}
}
// upload image data to firebase
let imagesFolder = Storage.storage().reference().child("images")
if let image = myImage.image {
if let imageData = image.jpegData(compressionQuality: 0.75) {
imagesFolder.child("\(NSUUID().uuidString).jpg").putData(imageData, metadata: nil,completion: { (metadata,error) in
if let error = error {
// alert notification
}
// putData(_:metadata:completion:)
})
}
}
I have crazy comment please ignore that !

I have found the answer myself for future coders this can be a reference !
// user info stored
let userID = Auth.auth().currentUser?.uid
let userData = ["userName": userName,
"userAge ": userAge] as [String? : Any]
let ref = Database.database().reference()
ref.child("users/\(userID ?? "")").setValue(userData)
}
now to retrieve data create a struct and put the code in view did load
func fetchCurrentUserData() {
guard let currentUid = Auth.auth().currentUser?.uid else { return }
let userRef = Database.database().reference().child("users").child(currentUid)
print("userRef: \(userRef)")
userRef.observeSingleEvent(of: .value) { (snapshot) in
guard let dictionary = snapshot.value as? Dictionary<String, AnyObject> else { return }
let uid = snapshot.key
let user = User(uid: uid, dictionary: dictionary)
self.user = user
print(snapshot.key)
}
}

Related

Displaying Username in Swift and FireBase

I'm trying to display the users username that stored in firebase. I'm not sure if Im saving the username correctly or if that's even the problem. I can't seem to access the data or display it at all. Any tips? I have a screenshot of the Cloud Firestore attached.
SignupViewController
import UIKit
import FirebaseAuth
import Firebase
import AVKit
import FirebaseFirestore
class SignUpViewController: UIViewController {
var videoPlayer:AVPlayer?
var videoPlayerLayer:AVPlayerLayer?
#IBOutlet weak var firstNameTextField: UITextField!
#IBOutlet weak var lastNameTextField: UITextField!
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var BackButton: UIButton!
#IBOutlet weak var UserNameTextField: UITextField!
#IBOutlet weak var signUpButton: UIButton!
#IBOutlet weak var errorLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing))
view.addGestureRecognizer(tap)
// Do any additional setup after loading the view.
setupElements()
}
func setupElements(){
//hides the error label
errorLabel.alpha = 0
//styles the text and buttons
Utilities.styleTextField(UserNameTextField)
Utilities.styleTextField(firstNameTextField)
Utilities.styleTextField(lastNameTextField)
Utilities.styleTextField(passwordTextField)
Utilities.styleTextField(emailTextField)
Utilities.styleFilledButton(signUpButton)
}
/*
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
// this function makes sure all data is good
func validateFields() -> String?
{
//make sure fields are filled
if firstNameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" || lastNameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" || emailTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" || UserNameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == ""
{
return "Please fill all fields"
}
let cleanPassword = passwordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
if Utilities.isPasswordValid(cleanPassword) == false{
return "Needs 8 charaters, number, and special charater"
}
return nil
}
#IBAction func signUpTapped(_ sender: Any) {
//validate fields
let error = validateFields()
if error != nil{
showError(error!)
}
else{
let firstName = firstNameTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let lastName = lastNameTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let email = emailTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let password = passwordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let username = UserNameTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
//create user
Auth.auth().createUser(withEmail: email, password: password) { result, err in
if err != nil{
self.showError("Error creating user")
}
else
{
//User is stored sucessfully, store the first and last name
let database = Firestore.firestore()
database.collection("UserInfo").addDocument(data: ["firstname": firstName,"email": email, "lastname": lastName, "username": username, "uid": result!.user.uid]) {(error) in
if error != nil
{
self.showError("First name and last name couldnt be saved.")
}
}
self.transitionToHome()
}
}
}
}
func showError(_ message:String){
errorLabel.text = message
errorLabel.alpha = 1
}
func transitionToHome(){
let homeViewController = storyboard?.instantiateViewController(identifier: Constants.StoryBoard.homeViewController) as?
HomeViewController
view.window?.rootViewController = homeViewController
view.window?.makeKeyAndVisible()
}
override func viewWillAppear(_ animated: Bool) {
//Set up video in background
setUpVideo()
}
func setUpVideo(){
//Get path to resource bundle
let bundlePath = Bundle.main.path(forResource: "IMG_7211 2", ofType: "mov")
guard bundlePath != nil else{
return
}
//create the url from it
let url = URL(fileURLWithPath: bundlePath!)
//Create The video Player item
let item = AVPlayerItem(url: url)
//create the player
videoPlayer = AVPlayer(playerItem: item)
//create the layer
videoPlayerLayer = AVPlayerLayer(player: videoPlayer!)
//adjust the size and frame
videoPlayerLayer?.frame = CGRect(x: -self.view.frame.size.width*1.5, y:0, width: self.view.frame.size.width*4, height: self.view.frame.size.height)
view.layer.insertSublayer(videoPlayerLayer!, at: 0)
//add and play
videoPlayer?.playImmediately(atRate: 0.8)
}
}
CurrentUser.swift
import Foundation
struct CurrentUser{
let uid: String
let name: String
let email: String
let profilepictureURL:String
init(uid: String, dictionary: [String: Any]){
self.uid = uid
self.name = dictionary["username"] as? String ?? ""
self.email = dictionary["email"] as? String ?? ""
self.profilepictureURL = dictionary["profilepictureURL"] as? String ?? ""
}
}
ProfileViewController
import UIKit
import Firebase
import FirebaseAuth
import FirebaseInstallations
import FirebaseFirestore
import FirebaseStorage
import FirebaseDatabase
class ProfileViewController: UIViewController {
#IBOutlet weak var SignOut: UIButton!
#IBOutlet weak var UserName: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
UserNameLabel()
// Do any additional setup after loading the view.
}
func UserNameLabel()
{
if Auth.auth().currentUser != nil
{
guard let uid = Auth.auth().currentUser?.uid else {return}
Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value) { (snapshot) in
guard let dict = snapshot.value as? [String: Any] else {return}
let user = CurrentUser(uid: uid, dictionary: dict)
self.UserName.text = user.username
}
}
}
#IBAction func SignOut(_ sender: Any) {
if Auth.auth().currentUser != nil {
do {
try Auth.auth().signOut()
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Vc")
vc.modalPresentationStyle = .fullScreen
present(vc, animated: true, completion: nil)
}
catch let error as NSError {
print(error.localizedDescription)
}
}
}
}
The problem is you are saving the data to Firebase Firestore, and then trying to access it from firebase real time database. Firebase Realtime Database and Firebase Firestore are 2 completely different backend servers and you are trying to use both at the same time. You need to pick only 1 and stick with it.
You are saving it to firebase firestore by using:
let database = Firestore.firestore()
database.collection("UserInfo").addDocument()
then after you save it to firestore you are trying to access it from real time database, not Firestore which is causing it to return nil:
Database.database().reference().child("users").child(uid).observeSingleEvent(of: .value) { (snapshot) in
So instead what you need to do is get it back from firestore by using this:
Firestore.firestore().collection("s").getDocuments { query, error in
for doc in query!.documents {
// Successfully retrieved data from firestore.
}
}
Note: You could also instead save it to the real time database instead of firestore, but it just depends which one will work better for your app. You need to pick either Firestore or the Database, you can't use both. Here is more info to help you decide which one is better. More Info

JSON Data is not fetched to Signuser model class properties to view properties in segued view controller labels in viewdidload

I have a model class of all string variables which i need to display in home view controller when user is successfully logged in.
I have created a seperate function to fetch and assign stuffs from user profile api and assign to model class.
and it's called in login function.
but after the segue to next view controller,Model class variables are still blank in it's viewdidload.(consider it as any viewcontroller )
import UIKit
import Alamofire
import SwiftyJSON
class LoginViewController: UIViewController {
var countries = [String]()
var cities = [String]()
let manager = APIManager()
#IBOutlet var txtUsername: UITextField!
#IBOutlet var txtPassword: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func ForgotPasswordAction(_ sender: UIButton) {
}
#IBAction func LoginButtonAction(_ sender: UIButton) {
let username = self.txtUsername.text
let password = self.txtPassword.text
if (username?.isEmpty)! || (password?.isEmpty)!{
self.showAlertWith(title: "Empty Username / Password", message: "Please check if username or password is entered")
}
else {
if Connectivity.isConnectedToInternet{
let parameter:Parameters = ["userItsId":username!,"password":password!]
manager.parsing2(url: BaseURL.login, parameter: parameter) { (JSON, Status) in
if Status { //login success
self.fetchUserProfile()
if JSON["status"] == "true"{
self.performSegue(withIdentifier: "login", sender:self)
}
else{
print("login failed")
}
}
else {
print("error occured,try again later")
}
}
}
else {
self.showAlertWith(title: "No Internet", message: "Please make sure that your device is connected to internet")
}
}
}
#IBAction func NotMemberAction(_ sender: UIButton) {
performSegue(withIdentifier: "register", sender: self)
}
#IBAction func SkipButtonAction(_ sender: UIButton) {
if Connectivity.isConnectedToInternet {
user.isLoggedin = false
performSegue(withIdentifier: "skip", sender: self )
}
else {
self.showAlertWith(title: "Connectivity Error", message: "Please check your connection and make sure that you are connected to the internet")
}
}
func fetchUserProfile(){
let userid = txtUsername.text
let parameter:Parameters = ["userItsId":userid!]
manager.parsing2(url: BaseURL.profile, parameter: parameter) { (JSON, Status) in
if Status{
let dict = JSON.dictionaryObject!
let data = dict["data"] as! [String:String]
let username = data["userName"]
let email = data["email"]
let UserId = data["userId"]
let nationality = data["nationality"]
let country = data["country"]
let mCity = data["mCity"]
let phoneNo = data["phoneNo"]
let dawatTitle = data["dawatTitle"]
let itsId = data["itsId"]
signUser.name = username!
signUser.email = email!
signUser.userID = UserId!
signUser.nationality = nationality!
signUser.country = country!
signUser.mCity = mCity!
signUser.phone = phoneNo!
signUser.dawatName = dawatTitle!
signUser.ItsId = itsId!
}
else {
print("fetching failed")
}
}
}
}

Cannot set value of Textfield as Firebase search result - Swift

I have a search function in my app to search my firebase db based on a pub name entered. This is working correctly & returning the correct record in my console. However I'm trying to display the relating info to that search query as values on my textfields.
var drinkReference: DatabaseReference!
let databaseRef = Database.database().reference()
#IBOutlet weak var pintImage: UIImageView!
#IBOutlet weak var pubName: UITextField!
#IBOutlet weak var pubLocation: UITextField!
#IBOutlet weak var price: UITextField!
#IBOutlet weak var rating: UITextField!
#IBOutlet weak var comment: UITextField!
#IBOutlet weak var searchText: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(AddDrinkVC .dismissKeyboard))
view.addGestureRecognizer(tap)
drinkReference = Database.database().reference().child("Drinks");
NotificationCenter.default.addObserver(self, selector: #selector(SearchVC.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(SearchVC.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
#IBAction func searchIsClicked(_ sender: Any) {
searchT()
}
#IBAction func homeClicked(_ sender: Any) {
homeClicked()
}
func searchT() {
// You must cast pub variable as String.
guard let pub: String = searchText.text else { return }
let databaseRef = Database.database().reference().child("Drinks")
let query = databaseRef.queryOrdered(byChild: "pub").queryStarting(atValue: pub).queryEnding(atValue: "\(String(describing: pub))\\uf8ff")
query.observeSingleEvent(of: .value) { (snapshot) in
guard snapshot.exists() != false else {
let alert = UIAlertController(title: "", message: "This pub hasn't been visited yet. We'll get there.", preferredStyle: UIAlertControllerStyle.alert)
let search = UIAlertAction(title: "Want to add the drink yourself?", style: .default) { [weak self] _ in
self?.uploadClicked()
}
alert.addAction(search)
alert.addAction(UIAlertAction(title: "Close & Search again", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
return }
print(snapshot.value as Any)
DispatchQueue.main.async {
guard let dict = snapshot.value as? [String:Any] else {
print(snapshot)
return
}
let returnedPubName = dict["pub"] as? String
let returnedPubLocation = dict["location"] as? String
let returnedPintPrice = dict["price"] as? String
let returnedPintRating = dict["rating"] as? String
let returnedComment = dict["comment"] as? String
self.pubName.text?.append(returnedPubName!)
self.pubLocation.text?.append(returnedPubLocation!)
self.price.text?.append(returnedPintPrice!)
self.rating.text?.append(returnedPintRating!)
self.comment.text?.append(returnedComment!)
}
}
}
When I try to assign the value of 'pubName' to the textfield of the same name it's receiving nil. Is this due to my 'guard let dict....' code?
Does anyone know how & where I'm going wrong here?
Thanks, E
Create a struct like this:-
struct Names {
var pub: String = ""
var location: String = ""
var price: String = ""
var rating: String = ""
var comment: String = ""
init(data: [String:Any]) {
if let obj = data["pub"] as? String {
self.pub = obj
}
if let obj = data["location"] as? String {
self.location = obj
}
if let obj = data["price"] as? String {
self.price = obj
}
if let obj = data["rating"] as? String {
self.rating = obj
}
if let obj = data["comment"] as? String {
self.comment = obj
}
}
}
And in your controller class create a variable
var names: [Names] = [Names]()
Then in your searchT method do this
guard let dict = snapshot.value as? [String:Any] else {
return
}
self.names.append(Names(data: dict))
print(self.names)
And then use
self.pubName.text = names.first?.pub
And if it not works just try after
DispatchQueue.main.async {
guard let dict = snapshot.value as? [String:Any] else {
return
}
self.names.append(Names(data: dict))
print(self.names)
}
self.pubName.text = names.first?.pub
So through trial and error & with the help of a few folk this is the working code, as a note I'm not sure if this is the most efficient way or anything, but it works so c'est la vie.
func searchT() {
// You must cast pub variable as String.
guard let pub: String = searchText.text else { return }
let databaseRef = Database.database().reference().child("Drinks")
let query = databaseRef.queryOrdered(byChild: "pub").queryStarting(atValue: pub).queryEnding(atValue: "\(String(describing: pub))\\uf8ff")
query.observeSingleEvent(of: .value) { (snapshot) in
guard snapshot.exists() != false else {
let alert = UIAlertController(title: "", message: "This pub hasn't been visited yet. We'll get there.", preferredStyle: UIAlertControllerStyle.alert)
let search = UIAlertAction(title: "Want to add the drink yourself?", style: .default) { [weak self] _ in
self?.uploadClicked()
}
alert.addAction(search)
alert.addAction(UIAlertAction(title: "Close & Search again", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
return }
print(snapshot.value as Any)
DispatchQueue.main.async {
// DATA WAS FOUND
for user_child in (snapshot.children) {
let user_snap = user_child as! DataSnapshot
let dict = user_snap.value as! [String: String?]
// DEFINE VARIABLES FOR LABELS
let returnedPubName = dict["pub"] as? String
let returnedPubLocation = dict["location"] as? String
let returnedPintPrice = dict["price"] as? String
let returnedPintRating = dict["rating"] as? String
let returnedComment = dict["comment"] as? String
self.pubName.text?.append(returnedPubName!)
self.pubLocation.text?.append(returnedPubLocation!)
self.price.text?.append(returnedPintPrice!)
self.rating.text?.append(returnedPintRating!)
self.comment.text?.append(returnedComment!)
}
}
}
}
Pay particular attention to the code following the comment //DATA WAS FOUND, that's accessing the values of the children data records.

Retrieving image from firebase? (swift)

So i have a firebase structure like the pic below
Now i want to retrieve that image file that i've uploaded. to decode the base64String and show it. Every user can make a post and the information that will be sended to firebase has a description etc. and also have an image. now i tried to retrieve it whit this codes but nothing did work.
var REF_LIST = Firebase(url: "\(URL_BASE)/listItems")
REF_LIST.observeEventType(FEventType.Value, withBlock: { snapshot in
let image = snapshot.value.objectForKey("images") as! String
but this already gave me a nil error on that line, so i couldn't even decode. i think i understand why it's giving me a nil error, there is no images in listItems on firebase, you first have the unique ID and then the specs with images in. now i don't now how i can retrieve that information from that unique ID?
UPDATE:
the tableViewController what will receive the data from firebase:
import UIKit
import FBSDKLoginKit
import Alamofire
import Firebase
class ListVC: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var lists = [List]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
dispatch_async(backgroundQueue, {
self.initObservers()
})
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.tableView.reloadData()
}
func initObservers() {
LoadingOverlay.shared.showOverlay(self.view)
DataService.ds.REF_LISTS.observeEventType(.Value, withBlock: { snapshot in
print(snapshot.value)
self.lists = []
if let snapshots = snapshot.children.allObjects as? [FDataSnapshot] {
for snap in snapshots {
print("SNAP: \(snap)")
if let listDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let list = List(listKey: key, dictionary: listDict)
self.lists.insert(list, atIndex:0)
}
}
}
self.tableView.reloadData()
LoadingOverlay.shared.hideOverlayView()
})
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return lists.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCellWithIdentifier("ListCell") as? ListCell {
let list = self.lists[indexPath.row]
cell.request?.cancel()
cell.configureCell(list)
return cell
} else {
return ListCell()
}
}
}
the addController which post the data to firebase:
import UIKit
import Firebase
import Alamofire
import FBSDKCoreKit
class AddVC: UIViewController, UITextFieldDelegate, UITextViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var addTitle: UITextField!
#IBOutlet weak var addDescription: UITextView!
#IBOutlet weak var addLocation: UITextField!
#IBOutlet weak var placeholderLbl: UILabel!
#IBOutlet weak var freeSwitch: UISwitch!
#IBOutlet weak var tradeSwitch: UISwitch!
#IBOutlet weak var imageSelectorImg: UIImageView!
#IBOutlet weak var overlayView: UIView!
var currentUsername = ""
var imageSelected = false
var imagePicker: UIImagePickerController!
var base64String: NSString = ""
override func viewDidLoad() {
super.viewDidLoad()
addTitle.delegate = self
addDescription.delegate = self
addLocation.delegate = self
imagePicker = UIImagePickerController()
imagePicker.delegate = self
getCurrentUser()
hideKeyboardWhenTappedAround()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
addTitle.text = ""
addDescription.text = ""
addLocation.text = ""
freeSwitch.setOn(false, animated: false)
tradeSwitch.setOn(false, animated: false)
placeholderLbl.hidden = false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getCurrentUser() {
DataService.ds.REF_USER_CURRENT.observeEventType(FEventType.Value, withBlock: { snapshot in
let currentUser = snapshot.value.objectForKey("username") as! String
print("Username: \(currentUser)")
self.currentUsername = currentUser }, withCancelBlock: { error in
print(error.description)
})
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
imagePicker.dismissViewControllerAnimated(true, completion: nil)
imageSelectorImg.image = image
dispatch_async(backgroundQueue, {
let uploadImage = image
let imageData = UIImageJPEGRepresentation(uploadImage, 0.5)
self.base64String = imageData!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
})
imageSelected = true
}
#IBAction func selectImage(sender: UITapGestureRecognizer) {
presentViewController(imagePicker, animated: true, completion: nil)
}
func postToFirebase() {
// LoadingOverlay.shared.showOverlay(self.overlayView)
var post: Dictionary<String, AnyObject> = ["username": self.currentUsername, "description": self.addDescription.text!, "title": self.addTitle.text!, "location": self.addLocation.text!, "images": self.base64String]
if self.freeSwitch.on && self.tradeSwitch.on {
post["tradeOption"] = "Gratis/Te ruil"
} else if self.freeSwitch.on {
post["tradeOption"] = "Gratis"
} else if self.tradeSwitch.on {
post["tradeOption"] = "Te ruil"
}
let firebasePost = DataService.ds.REF_LISTS.childByAutoId()
firebasePost.setValue(post)
}
#IBAction func postListItem(sender: AnyObject) {
if let addTitle = addTitle.text where addTitle != "", let addDescription = addDescription.text where addDescription != "", let addLocation = addLocation.text where addLocation != "" {
dispatch_async(backgroundQueue, {
self.postToFirebase()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let listVC = storyboard.instantiateViewControllerWithIdentifier("TBC") as! UITabBarController
listVC.selectedIndex = 1
self.presentViewController(listVC, animated: false, completion: nil)
})
})
}
}
func textViewDidBeginEditing(textView: UITextView) {
placeholderLbl.hidden = true
}
func textViewDidEndEditing(textView: UITextView) {
if textView.text == "" {
placeholderLbl.hidden = false
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
and the swift file to configure the cell:
import UIKit
import Alamofire
import Firebase
class ListCell: UITableViewCell {
#IBOutlet weak var listImg: UIImageView!
#IBOutlet weak var listTitle: UILabel!
#IBOutlet weak var listTradeOption: UILabel!
#IBOutlet weak var listLocation: UILabel!
#IBOutlet weak var headImg: UIImageView!
var list: List!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func retrieveImages() {
DataService.ds.REF_LISTS.observeEventType(FEventType.Value, withBlock: { snapshot in
if let snapshots = snapshot.children.allObjects as? [FDataSnapshot] {
for snap in snapshots {
let image = snap.value.objectForKey("images") as! String
let decodedData = NSData(base64EncodedString: image, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
let decodedImage = UIImage(data: decodedData!)
self.headImg.image = decodedImage
}
}
})
}
func configureCell(list: List) {
self.list = list
self.listTitle.text = list.listTitle
self.listTradeOption.text = list.listTradeOption
self.listLocation.text = list.listLocation
retrieveImages()
}
}
also the list Model file:
import Foundation
import Firebase
class List {
private var _listTitle: String!
private var _listDescription: String!
private var _listTradeOption: String!
private var _listLocation: String!
private var _listImageURL: String?
private var _listKey: String!
private var _listRef: Firebase!
var listTitle: String? {
return _listTitle
}
var listDescription: String? {
return _listDescription
}
var listTradeOption: String? {
return _listTradeOption
}
var listLocation: String? {
return _listLocation
}
var listKey: String {
return _listKey
}
var listImageURL: String? {
return _listImageURL
}
init(title: String, description: String, tradeOption: String, location: String, listImageURL: String?) {
self._listTitle = title
self._listDescription = description
self._listTradeOption = tradeOption
self._listLocation = location
self._listImageURL = listImageURL
}
init(listKey: String, dictionary: Dictionary<String, AnyObject>) {
self._listKey = listKey
if let title = dictionary ["title"] as? String {
self._listTitle = title
}
if let desc = dictionary ["description"] as? String {
self._listDescription = desc
}
if let trade = dictionary ["tradeOption"] as? String {
self._listTradeOption = trade
}
if let loc = dictionary ["location"] as? String {
self._listLocation = loc
}
if let imgUrl = dictionary["images"] as? String {
self._listImageURL = imgUrl
}
self._listRef = DataService.ds.REF_LISTS.childByAppendingPath(self._listKey)
}
}
i've got also a DataServicefile, where i create a user by unique ID with this code:
var REF_USER_CURRENT: Firebase {
let uid = NSUserDefaults.standardUserDefaults().valueForKey(KEY_UID) as! String
let user = Firebase(url: "\(REF_BASE)").childByAppendingPath("users").childByAppendingPath(uid)
return user!
}
func createFirebaseUser(uid: String, user: Dictionary<String, String>) {
REF_USERS.childByAppendingPath(uid).setValue(user)
}
i know it's a lot but maybe the best way to help :)
Try editing this in List Cell
var imageURL = String()
func retrieveImages() {
let decodedData = NSData(base64EncodedString: imageURL, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
let decodedImage = UIImage(data: decodedData!)
self.headImg.image = decodedImage
}
func configureCell(list: List) {
self.list = list
self.listTitle.text = list.listTitle
self.listTradeOption.text = list.listTradeOption
self.listLocation.text = list.listLocation
self.imageURL = list.listImageURL //you already had the image url for that specific cell
retrieveImages()
}
Storing and accessing images using base64String in firebase is not an
efficient way, instead of that we can use FirebaseStorage (Google cloud storage
bucket) for uploading images to Firebase and it will provide us
download URL for a particular image. We can store that URL into our database simply in a string format and access it whenever we
required and then download the corresponding image from that URL by
using SDWebImage.
Refer below link for integrating FirebaseStorage into your project: https://firebase.google.com/docs/storage/ios/upload-files

How to use presentViewController in a custom class?

I just update my code, but the alertWindow won't show up.
I add break point in Xcode, it shows that the viewDelegate is nil.
All delegates are nil.
This is my code:
class LoginViewController:UIViewController,AlertDelegate
{
override func viewDidLoad() {
super.viewDidLoad()
let BackGroundImage:UIImageView = UIImageView(frame: CGRectMake(0, 0, self.view.frame.width , self.view.frame.height))
let image: UIImage = UIImage(named: "backgroundLogin.jpg")!
BackGroundImage.image = image
self.view.addSubview(BackGroundImage)
//self.view.backgroundColor = UIColor(patternImage: UIImage(named: "backgroundLogin.jpg")!)
username.text = "User name"
password.text = "Password"
usernameWarning.text = ""
passwordWarning.text = ""
self.view.bringSubviewToFront(username)
self.view.bringSubviewToFront(password)
self.view.bringSubviewToFront(usernameText)
self.view.bringSubviewToFront(passwordText)
self.view.bringSubviewToFront(LoginButton)
self.view.bringSubviewToFront(RegisterButton)
self.view.bringSubviewToFront(usernameWarning)
self.view.bringSubviewToFront(passwordWarning)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
switch segue.identifier
{
case .Some("RegisterSegue"):
let registerViewController = segue.destinationViewController as! RegisterViewController
if let temp_register_username = usernameText!.text
{
registerViewController.register_name = temp_register_username
if let temp_register_pass = passwordText!.text
{
registerViewController.register_password = temp_register_pass
}
}
case .Some("loginSegue"):
let loginViewController = segue.destinationViewController as! FunctionsViewController
loginViewController.client = client
default:
super.prepareForSegue(segue, sender: sender)
}
}
override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {
if identifier == "loginSegue"
{
if usernameText.text != ""
{
if passwordText.text != ""
{
let encrypt = encryptMsg(send: passwordText.text!)
let encrypt_pass = encrypt.encryptSendMsg()
let sendMsg = AppConfig.AddHead("login", body: usernameText.text!+"|"+encrypt_pass)
let (_,_) = client.connect(timeout: 1)
let (success,_) = client.send(str: sendMsg)
if success
{
let data = client.read(1024*10)
if let d = data
{
if let str = String(bytes: d, encoding: NSUTF8StringEncoding)
{
if str[0...2] == AppConfig.TransmissionAgreementConfiguration["successLogin"]
{
AppConfig.StoreUserID(str)
let defaults = NSUserDefaults()
defaults.setObject(usernameText.text!, forKey: "userName")
let acceptThread = AcceptThread()
acceptThread.start()
return true
}
else if str[0...2] == AppConfig.TransmissionAgreementConfiguration["errLoginUsernameNotExist"]
{
usernameWarning.text = "User name doesn't exist"
usernameWarning.reloadInputViews()
passwordWarning.text = ""
passwordWarning.reloadInputViews()
return false
}
else if str[0...2] == AppConfig.TransmissionAgreementConfiguration["errLoginUsernameAlreadyOnline"]
{
usernameWarning.text = "User account already be online"
usernameWarning.reloadInputViews()
passwordWarning.text = ""
passwordWarning.reloadInputViews()
return false
}
else if str[0...2] == AppConfig.TransmissionAgreementConfiguration["errLoginPassword"]
{
usernameWarning.text = ""
usernameWarning.reloadInputViews()
passwordWarning.text = "Password Incorrect"
passwordWarning.reloadInputViews()
return false
}
}
}
}
return false
}
else
{
usernameWarning.text = ""
usernameWarning.reloadInputViews()
passwordWarning.text = "password cannot be empty"
passwordWarning.reloadInputViews()
return false
}
}
else
{
usernameWarning.text = "username cannot be empty"
usernameWarning.reloadInputViews()
return false
}
}
else
{
return true
}
}
func presentWindow(title:String,msg:String)
{
let alertController = UIAlertController(title: "\(title):", message: "\(msg)", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addTextFieldWithConfigurationHandler{
(textField: UITextField!) -> Void in
textField.placeholder = "Message"
}
let cancelAction = UIAlertAction(title: "Ignore", style: UIAlertActionStyle.Cancel, handler: nil)
let okAction = UIAlertAction(title: "Reply", style: UIAlertActionStyle.Default,
handler: {
action in
let reply_msg = alertController.textFields!.first! as UITextField
print("I replies \(reply_msg)")
})
alertController.addAction(cancelAction)
alertController.addAction(okAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
#IBAction func logoutUnwindSegue(segue: UIStoryboardSegue) {
// Intentionally left blank
}
var client:TCPClient = TCPClient(addr:"localhost",port:8889)
var AppConfig=TransmissionAgreement(first:"test")
#IBOutlet weak var usernameWarning: UILabel!
#IBOutlet weak var passwordWarning: UILabel!
#IBOutlet weak var username: UILabel!
#IBOutlet weak var password: UILabel!
#IBOutlet weak var usernameText: UITextField!
#IBOutlet weak var passwordText: UITextField!
#IBOutlet weak var LoginButton: UIButton!
#IBOutlet weak var RegisterButton: UIButton!
}
class AcceptThread: NSThread {
override func main() {
let server:TCPServer = TCPServer(addr:"127.0.0.1",port: 7000)
let (success,_) = server.listen()
if success
{
while !cancelled
{
if let my_client = server.accept()
{
let clientReadThread = ClientReadThread(client: my_client)
clientReadThread.start()
clientThreads.append(clientReadThread)
}
}
for clientThread in clientThreads {
clientThread.cancel()
}
}
}
var clientThreads = Array<ClientReadThread>()
var AppConfig=TransmissionAgreement(first:"test")
}
#objc protocol AlertDelegate: class {
func presentWindow(title:String,msg:String)
}
#objc protocol ClientReadThreadDelegate: class {
func clientReadThread(clientReadThread: ClientReadThread, didReceiveMessage message: String)
}
class ClientReadThread:NSThread{
init(client: TCPClient) {
self.client = client
super.init()
}
override func main() {
while !cancelled, let readValue = client.read(1024*10) {
if let message = String(bytes: readValue, encoding: NSUTF8StringEncoding) {
let head = message[0...2]
// print("head is \(head)")
if head! == AppConfig.TransmissionAgreementConfiguration["add"]
{
let defaults = NSUserDefaults()
let myname = defaults.stringForKey("userName")
//store data
let context = CoreDataService.sharedCoreDataService.mainQueueContext
let friend = NSEntityDescription.insertNewObjectForNamedEntity(Friends.self, inManagedObjectContext: context)
friend.name = message.substringFromIndex(3)
try! context.save()
let sendMsg = AppConfig.AddClientHead("agreeAdd", body:myname)
let (_,_) = client.send(str:sendMsg)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.delegate?.clientReadThread(self, didReceiveMessage: message)
})
}
else if head! == AppConfig.TransmissionAgreementConfiguration["chat"]
{
let search = message.substringFromIndex(3)
let resultController = try? catFriend.sharedCatFriendsService.catBlack(search)
try! resultController!.performFetch()
let flag = resultController?.sections?.count
if flag <= 1//friend
{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let client_info = message.split("|")
let client_name = client_info[1]
//self.alertDelegate?.presentWindow(client_name, msg: client_info[2])
self.viewDelegate?.presentWindow(client_name, msg: client_info[2])
})
}
else//black, not show the meg
{
//do nothing
}
}
}
}
}
var AppConfig=TransmissionAgreement(first:"test")
let client: TCPClient
var viewDelegate:LoginViewController?
var delegate: ClientReadThreadDelegate?
var alertDelegate: AlertDelegate?
private var resultController: NSFetchedResultsController?
}
presentViewContoller is a method on UIViewController so you'll need an instance of a view controller to be able to present your alert view.
The way this would normally be done is to have the view controller you have start the ClientReadThread implement the AlertDelegate protocol. There's no reason for ClientReadThread to implement AlertDelegate itself. Would it ever be it's own delegate?
Also you delegate's should be marked weak or else you'll end up with a retain cycle.
class MyViewController : UIViewController, AlertDelegate {
private var clientReadThread: ClientReadThread?
override viewDidLoad() {
super.viewDidLoad();
clientReadThread = ClientReadThread(someTcpClient)
clientReadThread.viewDelegate = self
}
func presentWindow(title:String,msg:String) {
// Your code goes here.
}
}
Your other option would be to pass an instance of a UIViewController into your ClientReadThread and use that to present the alert view. Although that's not the way I would go. the ClientReadThread shouldn't need to know how it's alerts are handled, that should be delegated to another class.