I'm writing an App, that takes information from an Excel document and saves the Data in Realm. My problem is, that every time I open the App, the Realm Database will save a copy of the Information. Now I get my TableViews with 3 times the same items.
Here is the code in my Main View Controller:
class ViewController: UIViewController {
let realm = try! Realm()
var importExcel = Import()
var xslxConvert = xslxConverter()
var currentString: [String] = []
var Name = ""
#IBOutlet weak var VRLabel: UIButton!
#IBOutlet weak var configurationLabel: UIButton!
#IBOutlet weak var Label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
currentString = importExcel.Results()
Label.text = Name
DispatchQueue.main.async {
self.saveData()
print("Data from Excel saved")
}
}
//MARK: - SaveData to the Realm
func saveData() {
do {
try realm.write {
for item in currentString {
let newItem = FunctionData()
newItem.functionName = item
realm.add(newItem)
}
}
} catch {
print ("Error trying to Realm data, \(error)")
}
}
}
How can I make a filter of something, to make that the App just save the Information from Excel ones?
Thanks a lot for the help!
Ok, I think it doesn't work with UUID(), because it will be different all time.
let filter = // choose what you need
if let items = Array(realm.objects(FunctionData.self).filter("parameterName == %#", filter)) {
// Do not save
} else {
// Save
}
And try to use realm.add(newItem, update: .modified) for saving
Related
If I just use the text field and run the app I can enter data in the text field and it stores in the Firebase database but when I close the application the data is gone from the text box , better yet it does not show in the UItextbox, i can type it and click submit to send the information to the server. So how can I show it again after the application is closed and reopened. I am using the cloud store in Firebase btw and using swift to code it in xcode
class viewcontroller5: UIViewController{
#IBOutlet weak var HowManyTextfield: UITextField!
#IBOutlet weak var WhatBrandTextField: UITextField!
#IBOutlet weak var HowOftenTextField: UITextField!
#IBOutlet weak var SubmitButton: UIButton!
// set document refenrence
let db = Firestore.firestore()
override func viewDidLoad() {
super.viewDidLoad()
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(self.swipeAction(swipe:)))
swipeRight.direction = UISwipeGestureRecognizer.Direction.right
self.view.addGestureRecognizer(swipeRight)
}
// Function to get the auto generated document ID
func getDocument(){
let docData : [String:Any] = [
"LastUpdated":FieldValue.serverTimestamp(),
"HoursOfSleep": HowManyTextfield.text! as String,
"BrandOfProducts": WhatBrandTextField.text! as String,
"HowManyTrims":HowOftenTextField.text! as String
]
guard let userID = Auth.auth().currentUser?.uid else {return}
// print(userID)
db.collection("Users").whereField("UID", isEqualTo: userID).getDocuments(){ (querySnapshot, err) in
if let err = err {
print(err.localizedDescription)
return
} else{
for document in querySnapshot!.documents{
if document == document{
print(document.documentID)
//create a profile collection and add the new information
let Profile = self.db.collection("Users").document(document.documentID)
Profile.updateData(docData){
err in
if let err = err{
print("error updating document: \(err)")} else { print("Document sucessfully updated")}
}
}
}
}
}
}
#IBAction func SubmitButton(_ sender: UIButton) {
globalDashboardVC?.FirstPage()
getDocument()
}
}
I'm trying to create a leaderboard, but the player names and scores are not permanently saved, the "leaderboard" only contains the data from the most recent game in its text view. I tried making arrayOfData initially hold playerName and finalScore instead of being an empty array, but the problem still remains. How can I display playerName and playerScore in the leaderboard permanently and hove more names and scores added as more people play?
var finalScore = Int()
var playerName = String()
var allMyStoredData = UserDefaults.standard
var arrayOfData: [Any] = []
class secondVC: UIViewController {
#IBOutlet weak var scoreLabel: UILabel!
#IBOutlet weak var nameTF: UITextField!
#IBOutlet weak var doneButton: UIButton!
var playerScore = 0
var arrayOfData: [Any] = []
override func viewDidLoad() {
super.viewDidLoad()
scoreLabel.text = "Your score is: \(finalScore)"
loadData()
}
#IBAction func donePressed(_ sender: Any) {
saveData()
performSegue(withIdentifier: "toLeaderboard", sender: self)
}
func saveData () {
playerName = nameTF.text!
playerScore = finalScore
arrayOfData.append(playerName)
arrayOfData.append(playerScore)
allMyStoredData.set(playerName, forKey: "saveTheName")
allMyStoredData.set(playerScore, forKey: "saveTheScore")
allMyStoredData.set(arrayOfData, forKey: "saveTheArray")
}
func loadData () {
if let loadPlayerName:String = UserDefaults.standard.value(forKey: "saveTheName") as? String {
playerName = loadPlayerName
}
if let loadTheScore:Int = UserDefaults.standard.value(forKey: "saveTheName") as? Int {
playerScore = loadTheScore
}
}
}
//this is the code in the leaderboard's view controller
class leaderboardViewController: UIViewController {
#IBOutlet weak var theTextView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
theTextView.text = "\((arrayOfData).map{"\($0)"}.joined(separator: " Score: "))"
}
}
You are overwriting your saveTheArray item UserDefaults each time with a new array.
You want to fetch the saved array first, append the new game data, then re-save as so:
//Create user defaults instance
let userDefaults = UserDefaults.standard
//User defaults key
let historicalGameDataKey = "historicalGameData"
//Fetch game data array
var historicalGameData = userDefaults.array(forKey: historicalGameDataKey)
//Create array if it is nil (i.e. very first game)
if historicalGameData == nil {
historicalGameData = []
}
//Create game data dictionary
let gameData = [
"playerName": playerName,
"playerScore": playerScore
]
//Append game data dictionary to the array
historicalGameData?.append(["playerName": gameData])
//Save the updated array
userDefaults.set(historicalGameData, forKey: historicalGameDataKey
Core Data would be a better way to store this data, but this example should solve your problem using UserDefaults.
Tell me what can be a mistake. I have 6 columns, two columns belong to TableViewCell. The other 4 belong to the ViewController. How do I tie the rows correctly so that the match information matches its row in TableViewCell.
import UIKit
import Parse
class DetailTennisViewController: UIViewController {
#IBOutlet weak var imageTennis: UIImageView!
#IBOutlet weak var outClose: UIButton!
#IBOutlet weak var titleTennis: UILabel!
#IBOutlet weak var textTennis: UITextView!
#IBOutlet weak var progTennis: UILabel!
#IBAction func closeOut(_ sender: Any) {
dismiss(animated: false, completion: nil)
}
var tenises : Tennis?
func configureButton() {
outClose.layer.cornerRadius = 0.5 * outClose.bounds.size.width
outClose.clipsToBounds = true
}
override func viewDidLoad() {
super.viewDidLoad()
loadTennis()
configureButton()
}
func loadTennis () {
let qwery = PFQuery(className: "tennis")
qwery.getFirstObjectInBackground() { (object,error) ->Void in
if error == nil {
self.textTennis.text = object!["textTen"] as? String
self.progTennis.text = object!["progTen"] as? String
self.titleTennis.text = object!["titleTen"] as? String
let imageFile = object!["tenImage"] as? PFFile
imageFile?.getDataInBackground() { (data:Data?, error:Error?)->Void in
if error == nil {
if let imageData = data {
self.imageTennis.image = UIImage(data: imageData)
}
}
}
}
}
}
}
How to make the data string Parse.com How to make the data TableViewCell cells corresponded to the description ViewController. In my code, when the cell is opened, the same data is displayed. I uploaded 4 events and information about them. So the information about them opens up the same. How to make the one that is indicated by their "objectId"
I have an xCode project and I want to reload a label which contain the user score,
here is the code:
#IBOutlet weak var moneyLabel: UILabel!
#IBOutlet weak var imageMoneyMove: UIImageView!
var managedObjextContext:NSManagedObjectContext!
var coreDataMoney = [Money] ()
var money:Int = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
managedObjextContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
loadData()
let moneyItem = Money(context: managedObjextContext)
moneyLabel.text! = String(moneyItem.allMoney)
}
func loadData() {
let presentRequest:NSFetchRequest<Money> = Money.fetchRequest()
do {
coreDataMoney = try managedObjextContext.fetch(presentRequest)
} catch {
print("Could not load data from database \(error.localizedDescription)")
}
}
#IBAction func addMoney(_ sender: Any) {
let moneyItem = Money(context: managedObjextContext)
money += 1
moneyItem.allMoney = Float(money)
moneyLabel.text! = String(moneyItem.allMoney)
print(moneyItem.allMoney)
do {
try self.managedObjextContext.save()
self.loadData()
}catch {
print("Could not save data \(error.localizedDescription)")
}
print(moneyItem.allMoney)
}`
I have an Entity called Money and an attribute of type Float and named allMoney. Thank you !
Assuming you have an Entity Money with is supposed to contain a single record I recommend to implement a computed property with custom getter and setter.
I renamed coreDataMoney with money and money with amount
First of all declare variable for the Money object and a lazy instantiated variable for the managed object context.
var money : Money!
lazy var managedObjextContext : NSManagedObjectContext = {
return (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
}()
Declare the variable amount.
The getter checks if the variable money containing the NSManagedObject is nil. If yes, the object is loaded, then the value is returned.
The setter updates the value in the NSManagedObject object, saves the context and updates the label.
var amount : Float {
get {
if money == nil {
loadData()
}
return money.allMoney
}
set {
money.allMoney = newValue
saveContext()
moneyLabel.text! = String(newValue)
}
}
Create a convenience method to save the context.
func saveContext() {
do {
try self.managedObjextContext.save()
} catch {
print("Could not save data \(error.localizedDescription)")
}
}
The loadData() method load the Money object. If the entity is empty create one.
func loadData() {
let presentRequest:NSFetchRequest<Money> = Money.fetchRequest()
do {
let coreDataMoney = try managedObjextContext.fetch(presentRequest)
if coreDataMoney.isEmpty {
let moneyItem = Money(context: managedObjextContext)
money = moneyItem
saveContext()
} else {
money = coreDataMoney.first!
}
} catch {
print("Could not load data from database \(error.localizedDescription)")
}
}
In viewDidLoad get the variable amount to load the data and update the label.
override func viewDidLoad() {
super.viewDidLoad()
moneyLabel.text! = String(amount)
}
Finally in the addMoney method just increment the amount property. The setter logic updates the CoreData stack and the label.
#IBAction func addMoney(_ sender: Any) {
amount += 1.0
}
I'm working on an app, that should request some data from my server. I'm using Alamofire to do that, and then use SWXMLHash to parse the XML data. There are two View Controllers, on the first one I can write a shipment number, then override function prepareForSegue and send that number to the next View Controller that should display data from server and updateUI on viewDidLoad, but it does not. Where is a problem?
My Class:
class Shipment {
private var _shipmentNumber: String!
private var _shipmentStatus: String!
private var _trackURL: String!
var shipmentNumber: String {
if _shipmentNumber == nil {
_shipmentNumber = ""
}
return _shipmentNumber
}
var shipmentStatus: String {
if _shipmentStatus == nil {
_shipmentStatus = ""
}
return _shipmentStatus
}
init(spNumber: String) {
self._shipmentNumber = spNumber
_trackURL = "..."
}
func requestXmlInformation(completed: DownloadComplete) {
let url = NSURL(string: _trackURL)!
Alamofire.request(.GET, url).responseData { response in
if let xmlToParse = response.data as NSData! {
let xml = SWXMLHash.parse(xmlToParse)
do {
let xmlSpWeight = try xml["fmresultset"]["resultset"]["record"]["field"].withAttr("name", "ТotalWeight")["data"].element!.text! as String
self._shipmentStatus = xmlSpStatus
print(self._shipmentStatus)
} catch let err as NSError {
print(err.debugDescription)
}
}
}
}
}
My Second View Controller
#IBOutlet weak var numberLbl: UILabel!
#IBOutlet weak var weightLbl: UILabel!
#IBOutlet weak var statusLbl: UILabel!
#IBOutlet weak var packageQtyLbl: UILabel!
var shipment: Shipment!
override func viewDidLoad() {
super.viewDidLoad()
shipment.requestXmlInformation { () -> () in
self.updateUi()
print(self.statusLbl.text)
}
}
updateUI function:
func updateUi() {
numberLbl.text = shipment.shipmentNumber
weightLbl.text = shipment.shipmentWeight
statusLbl.text = shipment.shipmentStatus
packageQtyLbl.text = shipment.shipmentPackageQty
}
It prints data in terminal but i think updateUI function does not work.
Make sure that the code in your requestXmlInformation closure is called on the main thread. You shouldn't update the UI in background threads.
shipment.requestXmlInformation { () -> () in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.updateUi()
print(self.statusLbl.text)
})
}
Also, you don't seem to call the complete closure anywhere in your requestXmlInformation method