I already search in the internet, I still don't understand how to insert a value to a variable. im trying to insert a value to a variable so i can append it into an array and then put it inside a tableviewcell.
I understand how the cells works, i just wanted to know how can i insert a data to this variable
Here's the code for my struct
import Foundation
import UIKit
enum issueType: String {
case major = "Major", blocker = "Blocker", minor = "Minor"
}
struct Issue {
var id: String
var tester: String
var type: issueType
var title: String
var appName: String
var desc: String
var date: Date
var bgColor: UIColor?
init(){
id = ""
tester = ""
type = .minor
title = ""
appName = ""
desc = ""
date = Date()
bgColor = UIColor.main()
}
init(item: [String:Any]){
self.init()
id = item["id"] as? String ?? ""
tester = item["tester"] as? String ?? ""
title = item["title"] as? String ?? ""
appName = item["appName"] as? String ?? ""
desc = item["desc"] as? String ?? ""
if type == .major {
bgColor = UIColor.main()
}
else if type == .blocker {
bgColor = UIColor.blue
}
else {
bgColor = UIColor.green
}
}
}
Here's the code for the variable in the superDidLoad from different a class
override func viewDidLoad() {
super.viewDidLoad()
var issue1 = Issue(id: "id", tester: "tester", type: .minor, title: "title", appName: "appName", desc: "desc", date: Date())
issue1.bgColor = UIColor.main()
array.append(issue1)
}
Your UITableViewCell subclass should have some variable of type Issue
class YourSubclass: UITableViewCell {
var issue: Issue?
...
}
then in cellForRowAt TableView data source method assign cell's variable as element from array with index equal to indexPath.row
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
cell.issue = array[indexPath.row]
...
}
After adding your own initializer to the struct you lost default memberwise initializer.
To avoid this use extension:
struct Issue {
var id: String
var tester: String
var type: issueType
var title: String
var appName: String
var desc: String
var date: Date
var bgColor: UIColor?
}
extension Issue {
init(){
id = ""
tester = ""
type = .minor
title = ""
appName = ""
desc = ""
date = Date()
bgColor = UIColor.main()
}
init(item: [String:Any]){
self.init()
id = item["id"] as? String ?? ""
tester = item["tester"] as? String ?? ""
title = item["title"] as? String ?? ""
appName = item["appName"] as? String ?? ""
desc = item["desc"] as? String ?? ""
if type == .major {
bgColor = UIColor.main()
}
else if type == .blocker {
bgColor = UIColor.blue
}
else {
bgColor = UIColor.green
}
}
}
But even in this case you must to init all properties by default initializer including 'bgColor'.
var issue1 = Issue(id: "id", tester: "tester", type: .minor, title: "title", appName: "appName", desc: "desc", date: Date(), bgColor: nil)
Related
I need to migrate my Realm DB in Swift and getting errors due to duplicate values in regards to primary key.
I have reviewed both models and the migration block several times and cannot find my error. That's why I'd be thankful for any hints that might help.
Old data model:
class LabelObject: Object, Codable {
#objc dynamic var identifier: String = UUID().uuidString
#objc dynamic var geo_latitude: Double = 0
#objc dynamic var geo_longitude: Double = 0
#objc dynamic var geo_radius: Double = 300
#objc dynamic var info_text: String = ""
#objc dynamic var info_icon: String = ""
#objc dynamic var info_placemark: String = ""
#objc dynamic var color_red: Float = Float(UIColor.systemBlue.cgColor.components?[0] ?? 0)
#objc dynamic var color_green: Float = Float(UIColor.systemBlue.cgColor.components?[1] ?? 0)
#objc dynamic var color_blue: Float = Float(UIColor.systemBlue.cgColor.components?[2] ?? 0)
#objc dynamic var color_alpha: Float = 1
override class func primaryKey() -> String? {
return "identifier"
}
}
New data model:
class LabelObject: Object {
#Persisted var identifier: String = UUID().uuidString
#Persisted var geo_latitude: Double = 0
#Persisted var geo_longitude: Double = 0
#Persisted var geo_radius: Double = 150
#Persisted var info_icon: String = "tag"
#Persisted var info_text: String = ""
#Persisted var info_placemark: String = ""
#Persisted var color_red: Double = Double(UIColor.systemBlue.cgColor.components?[0] ?? 0)
#Persisted var color_green: Double = Double(UIColor.systemBlue.cgColor.components?[1] ?? 0)
#Persisted var color_blue: Double = Double(UIColor.systemBlue.cgColor.components?[2] ?? 0)
#Persisted var color_alpha: Double = Double(UIColor.systemBlue.cgColor.components?[3] ?? 1)
override class func primaryKey() -> String? {
return "identifier"
}
}
Migration block:
migration.enumerateObjects(ofType: "LabelObject") { oldObject, _ in
guard let oldObject = oldObject else { return }
let newLabelObject: MigrationObject = migration.create("LabelObject")
newLabelObject["identifier"] = oldObject["identifier"] as? String ?? UUID().uuidString
newLabelObject["geo_latitude"] = oldObject["geo_latitude"] as? Double ?? 0
newLabelObject["geo_longitude"] = oldObject["geo_longitude"] as? Double ?? 0
newLabelObject["geo_radius"] = oldObject["geo_radius"] as? Double ?? georyCurrentConfiguration.preferenceLabelRadius
newLabelObject["info_text"] = oldObject["info_text"] as? String ?? ""
newLabelObject["info_icon"] = oldObject["info_icon"] as? String ?? ""
newLabelObject["info_placemark"] = oldObject["info_placemark"] as? String ?? ""
newLabelObject["color_red"] = newLabelObject["color_red"] as? Float ?? UIColor.systemBlue.cgColor.components?[0] ?? 0
newLabelObject["color_green"] = newLabelObject["color_green"] as? Float ?? UIColor.systemBlue.cgColor.components?[1] ?? 0
newLabelObject["color_blue"] = newLabelObject["color_blue"] as? Float ?? UIColor.systemBlue.cgColor.components?[2] ?? 0
newLabelObject["color_alpha"] = newLabelObject["color_alpha"] as? Float ?? UIColor.systemBlue.cgColor.components?[3] ?? 0
}
But I keep getting
Primary key property 'class_LabelObject.identifier' has duplicate values after migration.
Thanks for any hints!
You're telling your new object to use the same primary key as the old object, which isn't allowed
Let the new object populate the primary key on its own, which will copy the properties but assign it a unique ID.
It also appears the only difference is the new model is Codable and if that's the case it can be removed without a migration block as it's unrelated to Realm
Note that you only need local migrations for destructive changes like changing a property name or deleting a property.
I want to fetch the offerApplied value from the struct in another class. Here is the struct block:
struct Offer: JsonDeserilizer {
var offerDesC:String = ""
var discount:Double = 0.0
var offerId:String = ""
var offerCode:String = ""
var offerApplied:Int = 0
mutating func deserilize(values: Dictionary<String, Any>?) {
self.offerDesC = values?["offer_desc"] as? String ?? ""
self.discount = values?["discount"] as? Double ?? 0.0
self.offerId = values?["_id"] as? String ?? ""
self.offerCode = values?["offer_code"] as? String ?? ""
self.offerApplied = values?["is_applied"] as? Int ?? 0
}}
And an explanation will be very helpful.
You can create getter function in your struct, that can return specific value as you want. In target class initialise your struct properties (by calling deserilize(), or however you wish) and call the getter function to fetch values.
Update-:
As #Joakim mentioned, your properties are not private, so there is no need to create getter function. You could infact directly refer the property from created object.
struct Offer {
var offerDesC:String = ""
var discount:Double = 0.0
var offerId:String = ""
var offerCode:String = ""
var offerApplied:Int = 0
mutating func deserilize() {
self.offerDesC = "xy"
self.discount = 20
self.offerId = "okkk"
self.offerCode = "12"
self.offerApplied = 245
}
// func returnOfferApplied() -> Int{
// return offerApplied
// }
}
class xyz{
var obj = Offer()
func printOffer(){
obj.deserilize()
print(obj.offerApplied)
}
}
let obj = xyz()
obj.printOffer()
First create struct class at global file.
Look in my example
struct ColorPalette {
static let UEMColor = hexStringToUIColor(hex: "72279C")
static let uemIconPrimary = hexStringToUIColor(hex: "282D68")
}
Access Struct Like this:
ColorPalette.uemIconPrimary
I have problem with use data from firebase after get them. I written function getData() in model, use delegate to call them on UITableViewController and set data to TableView.
But when I create new array to get data from func getData(), this array is nil.
This is my model:
import Foundation
import Firebase
protocol myDelegate: class {
func didFetchData(datas: [Book])
}
class Book {
var Id: String?
var Author: String?
var ChapterCount: Int?
var CoverPhoto: String?
var Genre: String?
var Image: String?
var Intro: String?
var Like: Int?
var Name: String?
var Status: String?
var UpdateDay: String?
var UploadDay: String?
var View: Int?
var ref: DatabaseReference!
weak var delegate: myDelegate?
init()
{
}
init(Id: String,Author: String,Image: String,Name: String,Status: String,UpdateDay: String,View: Int)
{
self.Id = Id
self.Author = Author
self.Image = Image
self.Name = Name
self.Status = Status
self.UpdateDay = UpdateDay
self.View = View
}
func getListBook() {
ref = Database.database().reference()
ref.child("Book").observe(.value, with: { snapshot in
var newNames: [Book] = []
let value = snapshot.value as? NSDictionary
for nBook in value! {
let val = nBook.value as? NSDictionary
self.Name = val?["Name"] as? String ?? ""
self.Author = val?["Author"] as? String ?? ""
self.View = val?["View"] as? Int ?? 0
self.Status = val?["Status"] as? String ?? ""
self.Id = val?["Id"] as? String ?? ""
self.Image = val?["Image"] as? String ?? ""
self.UpdateDay = val?["UpdateDay"] as? String ?? ""
newNames.append(Book(Id: self.Id!, Author: self.Author!, Image: self.Image!, Name: self.Name!, Status: self.Status!, UpdateDay: self.UpdateDay!, View: self.View!))
}
self.delegate?.didFetchData(datas: newNames)
})
}
}
And there is class UITableViewController:
import Firebase
class ListStoryTableView: UITableViewController, myDelegate {
var ref: DatabaseReference!
var book = Book()
var listBook: [Book] = []
func didFetchData(datas: [Book]) {
listBook = datas
}
override func viewDidLoad() {
super.viewDidLoad()
let nib = UINib.init(nibName: "ListStoryTableViewCell", bundle: nil)
self.tableView.register(nib, forCellReuseIdentifier: "ListStoryTableViewCell")
book.delegate = self
book.getListBook()
print("\(listBook)") //this is return 0
}```
One solution would be to change-remove your protocol implementation and use a completion block in your getListBook func. Delete myDelegate reference from your ListStoryTableView and do the following change:
func getListBook(completion: #escaping (_ books: [Book]) -> Void) {
ref = Database.database().reference()
ref.child("Book").observe(.value, with: { snapshot in
var newNames: [Book] = []
let value = snapshot.value as? NSDictionary
for nBook in value! {
let val = nBook.value as? NSDictionary
self.Name = val?["Name"] as? String ?? ""
self.Author = val?["Author"] as? String ?? ""
self.View = val?["View"] as? Int ?? 0
self.Status = val?["Status"] as? String ?? ""
self.Id = val?["Id"] as? String ?? ""
self.Image = val?["Image"] as? String ?? ""
self.UpdateDay = val?["UpdateDay"] as? String ?? ""
newNames.append(Book(Id: self.Id!, Author: self.Author!, Image: self.Image!, Name: self.Name!, Status: self.Status!, UpdateDay: self.UpdateDay!, View: self.View!))
}
completion(newNames)
})
}
and then in your viewDidLoad or any other function you use the following to fetch your data:
book.getListBook { books in
listBook = books
tableView.reloadData()
}
I hope that helps you.
func didFetchData(datas: [Book]) {
listBook = datas
print("\(listBook)")
}
print listBook in this function and you will have the data..
EDIT 1: All spots where I define something related to the "author" variable (at bottom)
Can someone tell me why my labels still say "Optional()". My variables should be getting unwrapped through this code, should they not ? I am getting JSON data, parsing it into local objects and then using those objects in a table view (and a subsequent detail view) with labels.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let row = indexPath.row
guard let cell = tableView.dequeueReusableCellWithIdentifier(EditorialTableCellIdentifier, forIndexPath: indexPath) as? EditorialsTableViewCell else {
print ("error: editorialsTableView cell is not of class EditorialsTableViewCell, we will use RandomTableViewCell instead")
return tableView.dequeueReusableCellWithIdentifier(EditorialTableCellIdentifier, forIndexPath: indexPath) as! RandomTableViewCell
}
if let editorialObject = editorialObjects.objectAtIndex(indexPath.row) as? EditorialElement {
// we just unwrapped editorialObject
let title = editorialObject.title ?? "" // if editorialObject.title == nil, then we return an empty string.
let timeStampDateObject = NSDate(timeIntervalSince1970: NSTimeInterval(editorialObject.timeStamp))
let timeStampDateString = dateFormatter.stringFromDate(timeStampDateObject)
let author = editorialObject.author ?? ""
let issueNumber = editorialObject.issueNumber ?? ""
let volumeNumber = editorialObject.volumeNumber ?? ""
let articleContent = editorialObject.articleContent ?? ""
let nodeID = editorialObject.nodeID ?? 0
cell.editorialHeadlineLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
cell.editorialHeadlineLabel.text = title
cell.editorialAuthorLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
cell.editorialAuthorLabel.text = String(author)
cell.editorialPublishDateLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
cell.editorialPublishDateLabel.text = timeStampDateString
} else {
}
return cell
}
Class code:
class EditorialElement: NSObject {
var title: String // title
var nodeID: Int // nid
var timeStamp: Int // revision_timestamp
var imageURL: String // image_url
var author: String // author
var issueNumber: String // issue_int
var volumeNumber: String // volume_int
var articleContent: String // html_content
init(title: String, nodeID: Int, timeStamp: Int, imageURL: String, author: String, issueNumber: String, volumeNumber: String, articleContent: String) {
self.title = title
self.nodeID = nodeID
self.timeStamp = timeStamp
self.imageURL = imageURL
self.author = author
self.issueNumber = issueNumber
self.volumeNumber = volumeNumber
self.articleContent = articleContent
}
override func isEqual(object: AnyObject!) -> Bool {
return (object as! EditorialElement).nodeID == self.nodeID
}
override var hash: Int {
return (self as EditorialElement).nodeID
}
}
EDIT 1: Here is everything related to author (after edits)
In my IssueElement class:
var author: String // author
In my populateCurrentIssue function:
issueElement.author = String(node.1["author"])
In my cellForRowAtIndexPath (within the
if let currentIssueObject = currentIssueObjects.objectAtIndex(indexPath.row) as? IssueElement
loop.
let author = currentIssueObject.author
And finally:
cell.currentIssueArticlesAuthorLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
cell.currentIssueArticlesAuthorLabel.text = author
Looking at your code, editorialHeadlineLabel should not show "Optional()" in any case.
editorialAuthorLabel can be optional because String() can be optional if the constructor fails to initialize a string.
editorialPublishDateLabel can be optional because stringFromDate() will return nil if you pass an invalid date.
I have a tableview with a search bar. Search methods are okay, work well. I have a problem with didSelectRowAtIndexPath part.
When I select an list item (cell), need to pass this item to next scene with an segue.
But when I select an cell to show item details;
first selection: null object,
second selection: first object,
third selection: second object pass to next scene.
My vehicle class:
class Vehicle {
var owner : String
var plate : String
var location : String
var isOnline : String
var state : String
var speed : String
var driver : String
var maxSpeed : String
var dailyOverSpeed : String
var energy : String
var firstEngineDate : String
var messageDate : String
var dailyKm : String
var totalMoving : String
var totalWaiting : String
var totalParking : String
var totalKm : String
init() {
self.owner = ""
self.plate = ""
self.location = ""
self.isOnline = ""
self.state = ""
self.speed = ""
self.driver = ""
self.maxSpeed = ""
self.dailyOverSpeed = ""
self.energy = ""
self.firstEngineDate = ""
self.messageDate = ""
self.dailyKm = ""
self.totalMoving = ""
self.totalWaiting = ""
self.totalParking = ""
self.totalKm = ""
}
init(owner: String, plate: String, location: String, isOnline: String, state: String, speed: String, driver: String, maxSpeed: String, dailyOverSpeed: String, energy: String, firstEngineDate: String, messageDate: String, dailyKm: String, totalMoving: String, totalWaiting: String, totalParking: String, totalKm: String) {
self.owner = owner
self.plate = plate
self.location = location
self.isOnline = isOnline
self.state = state
self.speed = speed
self.driver = driver
self.maxSpeed = maxSpeed
self.dailyOverSpeed = dailyOverSpeed
self.energy = energy
self.firstEngineDate = firstEngineDate
self.messageDate = messageDate
self.dailyKm = dailyKm
self.totalMoving = totalMoving
self.totalWaiting = totalWaiting
self.totalParking = totalParking
self.totalKm = totalKm
}
}
My tableview controller:
class VehiclesTableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate{
...
var vehicles = [Vehicle]()
var filteredVehicles = [Vehicle]()
var selectedVehicle = Vehicle()
.....
}
didSelectRowAtIndexPath :
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if (tableView == self.tableView) {
self.selectedVehicle = vehicles[indexPath.row]
} else {
self.selectedVehicle = filteredVehicles[indexPath.row]
}
println(self.selectedVehicle.plate)
}
prepareForSegue :
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "DisplayViewSegue" {
var nextScene = segue.destinationViewController as! DisplayViewController
nextScene.currentVehicle = self.selectedVehicle
}
}
When I select any cell (with search or without search) my println() works corrent which is in didSelectRowAtIndexPath. Confused?
It sounds like you may have the searchbar as the top element of the tableview, so that when you acces an element from your vehicle array it needs to be indexPath.row-1. Also if you only segue when you select a row your can access the index directly with self.tableview.indexPathForSelectedRow() and use that to get the proper vehicle hope this fixes your problem