Cloudkit Database New Record does not save - ios

Please keep in mind that this is the first time I have used this website.
I am a complete beginner in coding who, somehow, ended up responsible for creating an app for a high-school level competition. My knowledge is extremely limited and I have found it difficult to find clear tutorials on how to use a CloudKit database.
My task for this specific portion of my application was to make a "Create a Profile" page, where users can input information that will then be stored and displayed in other ViewControllers of the application.
Most of the code related to the database was given by a teacher (taken out from the project of another group), yet its use was not explained. So, I simply tried to copy it and adapt it to the best of my abilities.
However, when running the simulator and creating a test profile, nothing happens once the save button is clicked.
My current code is as follows:
import UIKit
import CloudKit
class ProfileViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let database = CKContainer.defaultContainer().publicCloudDatabase
#IBOutlet weak var profileType: UISegmentedControl!
#IBOutlet weak var descriptionTextfield: UITextField!
#IBOutlet weak var nameTextfield: UITextField!
#IBOutlet weak var addressTextfield: UITextField!
#IBOutlet weak var emailTextfield: UITextField!
#IBOutlet weak var passwordTextfield: UITextField!
#IBOutlet weak var phoneTextfield: UITextField!
#IBOutlet weak var saveButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated
}
#IBAction func saveProfile(sender: AnyObject) {
let newrecord = CKRecord(recordType: "PotLuck")
newrecord.setObject(nameTextfield.text as CKRecordValue?, forKey: "CompanyName")
newrecord.setObject(addressTextfield.text as CKRecordValue?, forKey: "CompanyLocation")
newrecord.setObject(emailTextfield.text as CKRecordValue?, forKey: "CompanyEmail")
newrecord.setObject(passwordTextfield.text as CKRecordValue?, forKey: "CompanyPassword")
newrecord.setObject(phoneTextfield.text as CKRecordValue?, forKey: "CompanyPhone")
switch profileType.selectedSegmentIndex
{
case 0:
newrecord.setObject("Business" as CKRecordValue?, forKey: "CompanyType")
case 1:
newrecord.setObject("Charity" as CKRecordValue?, forKey: "CompanyType")
default:
break;
}
database.saveRecord(newrecord, completionHandler: {newrecord, error in
if error != nil {
print("An error occured")
} else {
let newview = URLViewController(nibName: "URLViewControler", bundle: nil)
self.presentViewController(newview, animated: true, completion: nil)
}
}
)
}
Would anyone be able to point out whatever is missing or incorrect?

Related

Value of type 'AuthDataResult' has no member 'uid' problem

I am a newbie in Swift, learning from building a social media app following a tutorial of Kasey Schlaudt on youtube. When I write this line KeychainWrapper.standard.set((user?.uid)!, forKey: "KEY_UID") at minutes 36:11 if this video: https://youtu.be/gBB5tnAzjjo?t=2171 I get this error —> Value of type 'AuthDataResult' has no member 'uid'. Any suggestions on why this might be happening?
This is my code so far:
import UIKit
import Firebase
import SwiftKeychainWrapper
class ViewController: UIViewController {
#IBOutlet weak var UserImageView: UIButton!
#IBOutlet weak var usernameField: UITextField!
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func signInPress(_ sender: Any) {
if let email = emailField.text, let password = passwordField.text {
Auth.auth().createUser(withEmail: email, password: password) { (user, error) in
if error != nil {
//Create account
} else {
KeychainWrapper.standard.set((user?.uid)!, forKey: "KEY_UID")
}
}
}
}
}
Any help would be much appreciated !
The API documentation for createUser says that it provides an AuthDataResult object as the result. As you can see from link, it doesn't have a uid property. You will want to use its user property to get a User object that does have a uid.
Auth.auth().createUser(withEmail: email, password: password) { (result, error) in
if error != nil {
//Create account
} else {
KeychainWrapper.standard.set((result?.user.uid)!, forKey: "KEY_UID")
}
}

Crashing when passing Var data as delegates

I have been trying to pass data back to my "HostRideViewController" from my "ProfileViewController" but the data I try to pass back creates a fatal error when unwrapping it, but i dont understand why as the console print out before it shows the correct data
import UIKit
import Foundation
import Firebase
protocol RiderSelectionDelegate {
func selectedRideLeader(firstName:String,lastName:String,uid:String)
}
class ProfileViewController: UIViewController {
#IBOutlet weak var ProfilePictureImageView: UIImageView!
#IBOutlet weak var AddasLeaderBtn: UIButton!
#IBOutlet weak var FirstNameFeild: UILabel!
#IBOutlet weak var LastNameFeild: UILabel!
#IBOutlet weak var UserBioFeild: UILabel!
#IBOutlet weak var HiddenEmail: UILabel!
#IBOutlet weak var HiddenUID: UILabel!
var user: MyUser?
var selectedFirstName: String?
var selectedLastName: String?
var selectedUID: String?
var selectedEmail: String?
var selectionDelegate: RiderSelectionDelegate!
override func viewDidLoad() {
super.viewDidLoad()
/// make profile picture circular
ProfilePictureImageView.layer.cornerRadius = ProfilePictureImageView.frame.size.width/2
ProfilePictureImageView.clipsToBounds = true
/// load user data into view
FirstNameFeild?.text = user?.firstName
LastNameFeild?.text = user?.lastName
HiddenUID?.text = user?.uid
HiddenEmail?.text = user?.email
}
#IBAction func SelectedLeaderpressed(_ sender: Any) {
selectedFirstName = FirstNameFeild.text
selectedLastName = LastNameFeild.text
selectedUID = user?.uid
selectedEmail = user?.email
print(selectedUID!,selectedLastName!,selectedFirstName!)
/// where the error is happening
selectionDelegate.selectedRideLeader(firstName:selectedFirstName!, lastName:selectedLastName!, uid:selectedUID!)
dismiss(animated: true, completion: nil)
}
}
My console output and error from passing data
49s64wH2g7hjiMAKp0uvADkzP0k2 bloggs joe
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file
My intended use of the delegate is to set a label up with the user's name
extension HostRideViewController:RiderSelectionDelegate{
func selectedRideLeader(firstName: String, lastName: String, uid: String) {
OtherRideLeaderLbl.text = firstName
}
}
where am I going wrong as I'm trying to force unwrap the data which is there and present in the print but crashes when I'm trying to delegate it
It seems selectionDelegate is nil you need to set it when you present/push/segue to the destination vc

Posting text field content to Firebase Database

I'm a newbie trying to connect my app to a backend (Firebase Database). Specifically, I have four fields where users enter content and I am trying to set a child node equal to each of those fields. Unfortunately, while I get no errors, nothings posts in the database. I'm not sure if I'm missing something big or small so any guidance would be really appreciated. Code is below:
class ThirdViewController: UIViewController {
var ref:FIRDatabaseReference!
#IBOutlet weak var bookTitle: UITextField!
#IBOutlet weak var bookDescription: UITextField!
#IBOutlet weak var authorBiography: UITextView!
#IBOutlet weak var bookPurchaseLink: UITextView!
#IBAction func saveButtonTapped(_ sender: Any) {
let bookTitleContent = String(describing: bookTitle.text)
let bookDescriptionContent = String(describing: bookDescription.text)
let authorBiographyContent = String(describing: authorBiography.text)
let bookPurchaseLinkContent = String(describing: bookPurchaseLink.text)
func viewDidLoad() {
super.viewDidLoad()
//post to database
ref = FIRDatabase.database().reference()
self.ref.child(uuid).child("Book Info").child("Book Title").setValue(bookTitleContent)
self.ref.child(uuid).child("Book Info").child("Book Description").setValue(bookDescriptionContent)
self.ref.child(uuid).child("Book Info").child("Author Biography").setValue(authorBiographyContent)
self.ref.child(uuid).child("Book Info").child("Book Purchase Link").setValue(bookPurchaseLinkContent)
}
}
Check Firebase Rules to Read And write.!
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
mdatabase = FirebaseDatabase.getInstance();
mdatabaseReference = mdatabase.getReference();
mdatabaseReference.child("Child").setValue(Data);
//
Kindly have a look at documentation
hope this may help you.!

Initializing AVAudioPlayer to be used in more than one function

Usual AVAudioPlayer tutorials online creates a AVAudioPlayer within a function to where the play and stop functions of the AVAudioPlayer object aren't available to the object directly from other functions. The problem is that I would like another function to stop the sound from the AVAudioPlayer. This seems pretty simple by initializing the objects at the top of the class in hopes it would be accessible however in Swift3 the init function for AVAudioPlayer includes a throw and a parameter for the sound file. Swift doesn't allow us to use an instance member within a property initializer so I'm stuck on my thought process of how this could be written.
The only error I'm running into at this point is not being allowed to use an instance member in the property initializer when creating "backgroundMusicPlayer":
import UIKit
import AVFoundation
class MadLibOneViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var thePlace: UITextField!
#IBOutlet weak var theVerb: UITextField!
#IBOutlet weak var theNumber: UITextField!
#IBOutlet weak var theTemplate: UITextView!
#IBOutlet weak var theStory: UITextView!
#IBOutlet weak var generateStoryButton: UIButton!
#IBOutlet weak var proceedToNextMadLib: UIButton!
//var backgroundMusicPlayer = AVAudioPlayer()
var error:NSError?
var path = Bundle.main.path(forResource: "bensound-cute", ofType: "mp3")
var url: NSURL {
return NSURL(fileURLWithPath: path!)
}
var backgroundMusicPlayer: AVAudioPlayer = try AVAudioPlayer(contentsOf: url as URL, error: &error)
#IBAction func createStory(_ sender: AnyObject) {
theStory.text=theTemplate.text
theStory.text=theStory.text.replacingOccurrences(of: "<place>", with: thePlace.text!)
theStory.text=theStory.text.replacingOccurrences(of: "<verb>", with: theVerb.text!)
theStory.text=theStory.text.replacingOccurrences(of: "<number>", with: theNumber.text!)
generateStoryButton.isHidden=true
proceedToNextMadLib.isHidden=false
}
#IBAction func showNextStory(_ sender: AnyObject) {
view.backgroundColor=UIColor.green
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let resultViewController = storyBoard.instantiateViewController(withIdentifier: "MadLibTwoViewController") as! MadLibTwoViewController
self.present(resultViewController, animated:true, completion:nil)
}
#IBAction func hideKeyboard(_ sender: AnyObject) {
thePlace.resignFirstResponder()
theVerb.resignFirstResponder()
theNumber.resignFirstResponder()
theTemplate.resignFirstResponder()
}
override func viewDidLoad() {
super.viewDidLoad()
proceedToNextMadLib.isHidden=true
view.backgroundColor = UIColor.purple
// Do any additional setup after loading the view.
self.theVerb.delegate = self
self.thePlace.delegate = self
self.theNumber.delegate = self
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You need to use Lazy initialisation/instantiation for that. In your case this is all you need to do.
lazy var player: AVAudioPlayer = {
[unowned self] in
do {
return try AVAudioPlayer.init(contentsOf: self.url)
}
catch {
return AVAudioPlayer.init()
}
}()
For more about Lazy Initialisation this is a good read. The interesting thing in your case is that the initialiser throws. I think this forum discussion is helpful to have a slight idea.

Uncaught Exception Saving String NSUserDefaults [Swift]

I am trying to save an inputted string from a text field and load that saved value using NSUserDefaults. When I run my code, the app crashes when I hit the "saveScore" button. My error message is "terminating with uncaught exception," but I can't find what's actually wrong.
class ScoreViewController: UIViewController {
#IBOutlet weak var loadDataButton: UIButton!
#IBOutlet weak var mathScore: UITextField!
#IBOutlet weak var testMath: UILabel!
#IBOutlet weak var saveScore: UIButton!
#IBOutlet weak var displayDataLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func saveDataClicked(sender: AnyObject) {
saveData()
}
func saveData() {
let defaults = NSUserDefaults.standardUserDefaults()
let latestScore = mathScore.text
defaults.setObject(latestScore, forKey: "12/1")
defaults.synchronize()
}
#IBAction func loadDataClicked(sender: AnyObject) {
var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
if let firstNameIsNotNill = defaults.objectForKey("12/1") as? String {
self.displayDataLabel.text = defaults.objectForKey("12/1") as String
}
}
Restarting XCode fixed the problem!

Resources