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
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 just started Swift and I am having problems.
I want pagination, and I coded this.
model:
struct MoreListAppand {
var MoreNoticeListModel : [MoreNoticeListModel] = []
mutating func addTask(task: MoreNoticeListModel){
MoreNoticeListModel.append(task)
}
}
struct MoreNoticeListModel {
var pageInfo : PageInfoFragmentModel? = nil
var totalCount : Int = 0
var edges: [NoticeInfoModel] = []
mutating func map(MoreNoticeListModel item: NoticeList){
self.pageInfo = nil
let pageData = item.pageInfo
var pageModel = PageInfoFragmentModel()
pageModel.map(item: pageData.fragments.pageInfoFragment)
self.pageInfo = pageModel
self.totalCount = item.totalCount
print("NoticeList totalCount == ", self.totalCount)
self.edges.removeAll()
for edge in item.edges! {
var edgeModel = NoticeInfoModel()
edgeModel.map(NoticeInfoModel:(edge?.fragments.edgesInfoFragment)!)
self.edges.append(edgeModel)
}
}
}
struct PageInfoFragmentModel {
// var hasNextPage : Bool << If I do not comment, an error will appear.(Missing argument for parameter 'hasNextPage' in call)
// var hasPreviousPage : Bool
var startCursor : String = ""
var endCursor : String = ""
mutating func map(item:PageInfoFragment) {
// self.hasNextPage = item.hasNextPage
// self.hasPreviousPage = item.hasPreviousPage
self.startCursor = item.startCursor
self.endCursor = item.endCursor
}
}
struct NoticeInfoModel {
var cursor : String = ""
var id : String = ""
var type: noticeType = .URGENT
var title: String = ""
var createdAt: String = ""
mutating func map(NoticeInfoModel item: EdgesInfoFragment){
self.cursor = item.cursor
self.id = item.node.id
self.type = noticeType(rawValue: item.node.type.rawValue)!
self.title = item.node.title
self.createdAt = item.node.createdAt
print("NoticeList title == ", self.title)
print("NoticeList type == ", self.type)
}
}
and
#objc func myAction(_ sender : AnyObject) {
//sever connect
MoreAPI.shared.getNoticeList(first: 10, last: 0, offset: 0, after: "MjAxNy0xMi0wNVQxNzo1MDozMVo=", before: ""){
[unowned self] (noticeItemLists) in
self.noticeAddListDataModel?.addTask(task: noticeItemLists)
let indexPath:IndexPath = IndexPath(row:((self.noticeAddListDataModel?.MoreNoticeListModel.count)!), section:0) << this is error line
self.noticeListTable.reloadData()
}
}
self.noticeAddListDataModeldefined here
class MoreNoticeViewController: UIViewController {
var noticeAddListDataModel : MoreNoticeListModel? = nil
}
why PageInfoFragmentModel want "hasNextPage" parameter argument..?
I got error
"let indexPath:IndexPath = IndexPath(row:((self.noticeAddListDataModel?.MoreNoticeListModel.count)!), section:0)" line.
I do not know why I get this error....
The error Missing argument for parameter 'hasNextPage' in call states that you have a variable defined in the struct and not initialized. Since it is not initialized, you have to pass its value in the constructor call,i.e. where you are calling PageInfoFragmentModel(), you have to call PageInfoFragmentModel(hasNextPage: ). This constructor is defined by default by swift, if no constructor is defined. So to remove the bug, either you give it a value or make it an optional or pass its value in initialization. Read this : https://docs.swift.org/swift-book/LanguageGuide/Initialization.html for more info.
Follow naming convention, which is for variables camelCase.
struct MoreListAppand {
var MoreNoticeListModel : [MoreNoticeListModel] = []
mutating func addTask(task: MoreNoticeListModel){
MoreNoticeListModel.append(task)
}
}
here var var MoreNoticeListModel is Struct name, change it to var moreNoticeListModel.
1. why PageInfoFragmentModel want "hasNextPage" parameter argument..?
That is a model written by someone who added that variable that is why it is there, we won't be able to tell about that. If there is no use of those variables comment them.
2.
noticeAddListDataModel doesn't have any reference to MoreNoticeListModel instead it is of same type, you can't get count property from a model.
Maybe this is what you need ? self.noticeAddListDataModel?.totalCount or self.noticeAddListDataModel?.edges.count.
I want to see what user selected like the name of book and its assocaited chapters
I did this
struct bookChpt {
var book:[String] = []
var chapter:[[Int]] = []
}
let chptSelected = [bookChpt(book:bookArr,chapter:chptArr)]
var bookArr:[String] = []
var chptArr:[[Int]] = []
I have this in viewDidLoad()
if let bTitle = result.value(forKey: "bookTitle") as? String
{
bookArr.append(bTitle)
}
if let cNo = result.value(forKey: "chpNo") as? [Int]
{
chptArr.append(cNO)
}
print(chptSelected)
I am getting this
bookChpt( book: ["Hobbit", "LOTR"], chapter: [[3,5],4])
but I like to see this
["Hobbit", 3, 5], ["LOTR", 4]
There are a couple of possibilities. You could add a function to the struct to display its contents in the way you want:
struct BookChapter {
var book:[String] = []
var chapter:[[Int]] = []
func display() -> [[Any]] {
var output = [[Any]]()
for i in 0..<book.count {
output.append([book[i], chapter[i]])
}
return output
}
}
Or you could modify the structure of the struct to contain the book and chapters as tuples:
struct BookChapter {
var book:[(String, [Int])]
}
Going a bit further, anywhere you see a loop - such as in the display function above - you might also consider using map to achieve the same thing:
func display() -> Any {
return book.enumerated().map { $0.element + " " + chapter[$0.offset].description }
}
If you use an Dictionary like this, you can print the key and value whatever way you wanted.
var bookChapters = [String: [Int]]()
bookChapters["Hobbit"] = [1,2,3]
bookChapters["Hobbit"]?.append(contentsOf: [4])
for (book, chapter) in bookChapters {
print("\(book): \(chapter)")
}
Change your struct to
struct BookChapt {
var book: String = ""
var chapter: [Int] = []
}
and in viewDidLoad()
var bookName = ""
var chapters:[Int] = []
if let bTitle = result.value(forKey: "bookTitle") as? String
{
bookName = bTitle
}
if let cNo = result.value(forKey: "chpNo") as? [Int]
{
chapters = cNo
}
let chptSelected = BookChapt(book: bookName, chapter: chapters)
print(chptSelected)
I'm trying to save my array of objects in Realm, but Realm appears to be saving only the last object.
This is my model class:
class ContactEntry: Entry {
dynamic var contactId: Int = 0
dynamic var email: String? = ""
dynamic var phone: String? = ""
dynamic var building: String? = ""
dynamic var room: String? = ""
dynamic var contactDescription: String? = ""
dynamic var worktime: String? = ""
dynamic var address: String? = ""
dynamic var personEntries: PersonEntry?
}
This is the base class:
class Entry: Object {
dynamic var id: Int = 0
override static func primaryKey() -> String? { return "id" }
}
This is code I'm using for saving:
func createOrUpdate(entities: [Entity]) {
let entries = toEntries(entities)
let realm = try! Realm()
try! realm.write {
realm.add(entries, update: true)
}
}
func toEntry(entity: Contact) -> ContactEntry {
let entry = ContactEntry()
entry.contactId = entity.id
entry.email = entity.email
entry.phone = entity.phone
entry.building = entity.building
entry.room = entity.room
entry.contactDescription = entity.description
entry.worktime = entity.worktime
entry.address = entity.address
entry.personEntries = personDAO.toEntry(entity.person)
return entry
}
func toEntry(entity: Person) -> PersonEntry {
let entry = PersonEntry()
entry.personId = entity.id
entry.firstname = entity.firstname
entry.middlename = entity.middlename
entry.lastname = entity.lastname
entry.photo = entity.photo
return entry
}
I think that it may be because I have relationship in my model, but I'm not sure why they'd be a problem.
I'm using them as described in the Realm documentation.
According to the article http://www.weheartswift.com/swift-objc-magic/
I create a NSObject extension to parse JSON string to object
import Foundation
extension NSObject {
class func fromJson(jsonInfo: NSDictionary) -> Self {
var object = self()
(object as NSObject).load(jsonInfo)
return object
}
func load(jsonInfo: NSDictionary) {
for (key, value) in jsonInfo {
let keyName = key as String
if (respondsToSelector(NSSelectorFromString(keyName))) {
setValue(value, forKey: keyName)
}
}
}
func propertyNames() -> [String] {
var names: [String] = []
var count: UInt32 = 0
var properties = class_copyPropertyList(classForCoder, &count)
for var i = 0; i < Int(count); ++i {
let property: objc_property_t = properties[i]
let name: String = String.fromCString(property_getName(property))!
names.append(name)
}
free(properties)
return names
}
func asJson() -> NSDictionary {
var json:Dictionary<String, AnyObject> = [:]
for name in propertyNames() {
if let value: AnyObject = valueForKey(name) {
json[name] = value
}
}
return json
}
}
I create a Class inherited NSObject
import Foundation
class Weather : NSObject {
var date : String = ""
var currentCity : String = ""
var weather : String = ""
var wind : String = ""
var dayPictureUrl : String = ""
var nightPictureUrl : String = ""
var temperature : String = ""
}
then I build a helper to get API and parse result to Object
func requestApi(url :String, returnType: AnyClass, success: (res: AnyObject)->() ){
var queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)
var group = dispatch_group_create()
dispatch_group_async(group, queue) { () -> Void in
var url = NSURL.init(string:url)
var data = NSData.init(contentsOfURL:url!)
let jsonObj: AnyObject? = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments,error:nil)
if let topDict = jsonObj as? NSDictionary {
var obj : AnyObject = returnType.fromJson(topDict)
success(res: obj);
}
}
}
var api : String = "http://somesite.com/jsonapi"
requestApi(api, Weather.self, { (res) -> () in
// finish get the res obj
})
I know how to do it use Objective-C
but Swift I get this error at this line
LINE : var obj : AnyObject = returnType.fromJson(topDict)
ERROR : 'AnyClass' does not h``ave a member named from JSON
I don't know a lot about Swift,
I only want to call returnType class function ,
how can I do it ?
Your returnType is declared as being AnyClass. So of course it does not have a member fromJson. Probably you need to declare is as a class type that has this method.