shodai
shodai

Reputation: 25

How to add elements to a realm database

I am working on a simple app that catalogues information. Right now I am just trying to collect information and then add it to a realm database. Unfortunately I cannot figure it out and no matter what method I try (based on tutorials and the Realm website) I get the error "Use of unresolved identifier 'realm'. This is the code based on the command button executing the command.

@IBAction func Submit(_ sender: Any) {
    let myList = WineList()
    myList.vinyard = Vinyard.text
    myList.type = typeField.text
    myList.name = Name.text
    myList.grape = Grape.text
    myList.year = Year.text
    myList.price = Price.text
    myList.rating = rateField.text
    myList.purchased = purch
    myList.notes = Notes.text
    
    //from realm website example
    try! realm.write{
        realm.add(myList)
    }
    
    //from tutorials
    //realm.beginWrite()
    //realm.add(myList)
    //try realm.commitWrite()
}

Can anyone please advise me on what I am doing wrong? I will post all of my code below.

    import UIKit
import RealmSwift

class RankViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
    
    var purch = ""

    @IBOutlet weak var typeField : UITextField!
    @IBOutlet weak var rateField : UITextField!
    
    @IBOutlet weak var Vinyard: UITextField!
    @IBOutlet weak var Name: UITextField!
    @IBOutlet weak var Grape: UITextField!
    @IBOutlet weak var Year: UITextField!
    @IBOutlet weak var Price: UITextField!
    @IBOutlet weak var Notes: UITextField!
    
    @IBAction func Purchased(_ sender: UISwitch) {
        if (sender.isOn == true){
            purch = "Yes"
        }
        else {
            purch = "No"
        }
    }
    
    let wineTypes = ["Red","White","Rose","Sparkling","Ice - Red","Ice - White", "Port","Fruit","Other"]
    
    let wineRate = ["Hurray", "Meh", "Boo"]
    
    var typeView = UIPickerView()
    var rateView = UIPickerView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let realm = try! Realm()
        
        print (Realm.Configuration.defaultConfiguration.fileURL)
        
        typeView.delegate = self
        typeView.dataSource = self
        rateView.delegate = self
        rateView.dataSource = self
        Vinyard.delegate = self
        Name.delegate = self
        Grape.delegate = self
        Year.delegate = self
        Price.delegate = self
        Notes.delegate = self
        
        typeField.inputView = typeView
        rateField.inputView = rateView
        
    }
    
    public func numberOfComponents(in pickerView: UIPickerView) -> Int {
        if pickerView == typeView {
            // Returns for typeView
            return 1
        }
        else if pickerView == rateView {
            // Returns for rateView
            return 1
        }

        return 1
    }
        
    public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if pickerView == typeView {
            // Returns for typeView
            return wineTypes.count
        }
        else if pickerView == rateView {
            // Returns for rateView
            return wineRate.count
        }
        return wineRate.count
    }
        
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if pickerView == typeView {
            // Returns for typeView
            return wineTypes[row]
        }
        else if pickerView == rateView {
            // Returns for rateView
            return wineRate[row]
        }
            return wineRate[row]
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if pickerView == typeView {
            // Do stuff for typeView
            typeField.text = wineTypes[row]
            typeField.resignFirstResponder()
        }
        else if pickerView == rateView {
            // Do stuff for rateView
            typeField.text = wineRate[row]
            typeField.resignFirstResponder()
        }
    }
    
    
    @IBAction func Submit(_ sender: Any) {
        let myList = WineList()
        myList.vinyard = Vinyard.text
        myList.type = typeField.text
        myList.name = Name.text
        myList.grape = Grape.text
        myList.year = Year.text
        myList.price = Price.text
        myList.rating = rateField.text
        myList.purchased = purch
        myList.notes = Notes.text
        
        //from realm website example
        try! realm.write{
            realm.add(myList)
        }
        
        //from tutorials
        //realm.beginWrite()
        //realm.add(myList)
        //try realm.commitWrite()
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        Year.resignFirstResponder()
        Price.resignFirstResponder()
    }
}

extension RankViewController : UITextFieldDelegate{
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
    }

Separate file

    import Foundation
import RealmSwift

class  WineList: Object {
    @objc dynamic var vinyard: String?
    @objc dynamic var name: String?
    @objc dynamic var grape: String?
    @objc dynamic var year: String?
    @objc dynamic var price: String?
    @objc dynamic var notes: String?
    @objc dynamic var type: String?
    @objc dynamic var rating: String?
    @objc dynamic var purchased: String?
    
}

Upvotes: 1

Views: 442

Answers (1)

Jay
Jay

Reputation: 35667

Variables only exist with the function or class they are created. So take these two functions

func getData() {
   let realm = Realm()
   let results = realm.objects...
}

and

func printData() {
   print(results)   //this won't work
}

as you can see, the var 'realm' is instantiated in getData so that var is only available within that function and would not be available within the printData function.

In your case you've instantiated the realm var within viewDidLoad

override func viewDidLoad() {
   super.viewDidLoad()
        
   let realm = try! Realm()

therefore it will only be available within the viewDidLoad function.

To correct your issue, you need to instantiate realm within the function where you're trying to use it

@IBAction func Submit(_ sender: Any) {
    let myList = WineList()
    ...
    
    let realm = try! Realm()

    try! realm.write{
        realm.add(myList)
    }

to expand on that a bit. Take your RankViewController class

class RankViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
    
    var purch = ""

See the 'purch' var? That's called a 'class var' and because it's defined at a high level within the class, it would be available throughout the class.

func printData() {
   print(self.purch)   //this will work
}

note that I preceded purch with self. when I referenced it. To me, that's a good indicator it's a class var and makes the code more readable. However, it's not required.

Upvotes: 1

Related Questions