I'm new to Swift and have asked a few questions that I was somewhat confused about how to get the correct type for my object, but I believe I've figured it out.
I have a User object that is an Object Mapper model.
I am trying to convert this Object Mapper model to an Array.
https://github.com/Hearst-DD/ObjectMapper
However I am getting the error Cannot specialize a non-generic definition
Here is the variable I am trying to cast:
fileprivate var userDataSource = Mapper<User>().Array<Any>(User)
And an extension for its definition:
extension AccountViewController: GetUserDelegate {
func getUserSuccess(user: User) {
self.userDataSource = User
}
}
The original mapping to a model is done here:
guard let user = Mapper<User>().map(JSONObject: value)
The user class looks like this:
class User: Mappable {
required init?(map: Map) {
}
init() {}
var id: Int?
var firstName: String?
var lastName: String?
var displayName: String?
var image: URL?
var about: String?
var email: String?
var password: String?
var authToken: String?
I can include more if desired.
What am I misunderstanding here? None of the examples I'm seeing for this error really seem to apply to my situation.
Desired ultimate output:
["Name", "Bob Jim"],
["MC #", "1234567"],
["Company Name", "Bob's Truckin"],
["Truck Type", "Flat Bed"],
["Cell", "(555) 555-5555"],
["Dispatch", "(999) 999-9999"],
["Favorite Destinations", "Los Angeles"]
I gather you want an array of Users as the datasource,
I'd declare it like any other array:
var userDataSource = [User]()
or
var userDataSource = Array<User>()
And to update the datasource,
extension AccountViewController: GetUserDelegate {
func getUserSuccess(user: User) {
self.userDataSource.append(user)
}
}
Related
Tried to combine or merging two model to one model
1st model = items [ InboxModel]. (My own Inbox)
2nd model = items2 [MoInboxModel] (SDK Inbox)
1st + 2nd -> combinedItems
private var items: [InboxModel] = []
private var items2: [MoInboxModel] = []
private var combinedItems: [combinedInboxModel] = []
struct InboxModel {
let id: String
let title: String
let message: String
let date: Date
}
struct MoInboxModel {
let id: String
let title: String
let message: String
let date: Date
}
struct combinedInboxModel {
let id: String
let title: String
let message: String
let date: Date
}
self?.combinedItems.append(self?.items). //No exact matches in call to instance method 'append
self?.combinedItems.append(contentsOf: self?.items2 ?? []) //No exact matches in call to instance method 'append
Why there is an error while merge it ? How to merge it correctly?
You have three unrelated types - InboxModel, MoInboxModel and combinedInboxModel (Which should be CombinedInboxModel. Even though they all have properties with the same name, they are different types.
There is no append function on an array of combinedInboxModel that accepts an array of InboxModel or MoInboxModel.
You could use map on each of your two input arrays to convert them to an array of CombinedInboxModel which you can then put into combinedItems.
Presumably you are writing this code in a closure, which is why you have a weak self. Best to deal with that first and then process your arrays.
guard let self = self else {
return
}
self.combinedItems = self.items.map { CombinedInboxModel(id:$0.id,title:$0.title,message:$0.message,date:$0.date) }
let items2 = self.items2.map { CombinedInboxModel(id:$0.id,title:$0.title,message:$0.message,date:$0.date) }
self.combinedItems.append(contentsOf:items2)
You haven't shown where items and items2 come from; Is it possible just to fetch them as instances of the same struct to start with?
The fact that you have three structs with the same properties is a bit fishy. I would consider a different design if I were you.
However, if you must go with this approach, you might want to consider starting with a protocol and getting rid of the combinedInboxModel struct.
protocol InboxModelable {
var id: String { get }
var title: String { get }
var message: String { get }
var date: Date { get }
}
Now make your two structs conform to InboxModelable.
struct InboxModel: InboxModelable {
let id: String
let title: String
let message: String
let date: Date
}
struct MoInboxModel: InboxModelable {
let id: String
let title: String
let message: String
let date: Date
}
Since both of your types conform to InboxModelable you can directly store both types in an array of type Array<InboxModelable> without having to map the elements.
class SomeClass {
private var items: [InboxModel] = []
private var items2: [MoInboxModel] = []
private var combinedItems: [InboxModelable] = []
func combineItems() {
doSomething { [weak self] in
guard let self = self else { return }
self.combinedItems.append(contentsOf: self.items)
self.combinedItems.append(contentsOf: self.items2)
}
}
}
The object definition is:
struct Course: Identifiable, Hashable, Codable {
#DocumentID var id: String?
var country: String
var createdBy: String
}
I then embed this object as a member of a class as so:
class CourseRepository: ObservableObject {
private let path: String = "Courses"
private let store = Firestore.firestore()
#Published var courses: [Course] = []
...
In the snippet below, I only want the map result to contain courses where 'createdBy' == to the uid of the currently logged in user. But on the .filter statement, I get the following error:
emphasized text
**Value of type 'Published<[Course]>.Publisher.Output' (aka 'Array<Course>') has no member 'createdBy'**
MyCourseRepository.$courses
.filter { $0.createdBy == self.authState.loggedInUser!.uid }
.map { courses in courses.map(CourseViewModel.init)}
.assign(to: \.MyCourseViewModels, on: self)
.store(in: &cancellables)
}
Any help on this one much appreciated!
Right now, you're trying to filter the Publisher, whereas what you want to do is filter the items in the array that it's sending:
MyCourseRepository.$courses
.map { courseArray in
courseArray.filter { course in
course.createdBy == self.authState.loggedInUser!.uid
}
}
Consider the following classes
class Category {
var tag: String?
var itemList: [Item]?
}
class Item {
var id: Int?
var type: String?
var itemDetails: ItemDetails?
}
class ItemDetails {
var description: String?
var name: String?
var price: Float?
}
Given an array of Category objects.
var categoryList: [Category]
I want to create a new object array by extracting only the name in ItemDetails(inorder to apply a filter) and an id inorder to reconstruct back array of Category objects.
Hence, I have to reconstruct the array of Category objects
from new object array.
How to do both extraction and reconstruction using the map feature?
Below are the examples of other data sources:
Datasource 1 :
var categoryList: [Category], where name need to be extracted
Datasource 2 :
var searchList = [SearchItem], where title to be extracted.
Class SearchItem {
var id: Int?
var details: SearchItemDetails?
var type: String?
}
Class SearchItemDetails {
var description: String?
var title: String?
}
DataSource 3
var products: [Products], where title to be extracted.
Class Products {
var id: Int?
var details: ProductDetails?
var type: String?
}
class ProductDetails {
var description: String?
var title: String?
}
To get an array of just the names, you do the map like you mentioned:
let categories: [Category] = ... // this already exists
let itemNames = categories.map { $0.itemList?.map({ $0.itemDetails?.name }) }
But this will preserve optionals. If you don't want optionals, then use compactMap instead.
Reconstructing, however, doesn't really make any sense. Are you using the ID to hit a database or network service? That's the only possible way you'd be able to reconstruct the original array of Categorys. Why not just hold onto the original array?
I have stored a users home address in firebase as an array. It looks like this:
I am now trying to grab all of my users data and store them into a dictionary like this:
The User() part of the code is defined above like this:
var users = [User]()
the [User]() part of it comes from a user.swift file which is here:
class User: NSObject {
var fullName: String?
var email: String!
var userPhoto: String?
var homeAddress: [String:[Double]]()
var schoolOrWorkAddress: String!
}
the error is with the homeAddress part of it.
In the file I create variables for all my user data storage. My question now is how do I set home address to a value type of an array as that dictionaries key value. Can anyone help? Feel free to comment if you have any questions in helping me.
You could try to override the setValue function to iterate through homeAddress points.
// value in this case would be the points in your dictionary and the
// the key would be "homeAddress"
override func setValue(value: AnyObject?, forKey key: String) {
if key == "homeAddress" {
let homeAddressPoints = [HomeAddressPoint]()
for dict in value as! [[String: AnyObject]] {
let point = HomeAddressPoint()
point.setValuesForKeysWithDictionary(dict)
homeAddressPoints?.append(point)
}
} else {
super.setValue(value, forKey: key)
}
}
This is just an idea, and hopefully you can build from this.
I am new to using Realm. Is there an easy way to save an array to a realm object? I am receiving my data from a JSON REST call:
class SomeClass: RLMObject {
dynamic var id = 0
dynamic var name = ""
dynamic var array: NSArray
func checkForUpdates() {
// Download JSON data here... The results have an array inside of them.
SomeClass.createOrUpdateInDefaultRealmWithObject(SomeNSDictionary)
}
override class func primaryKey() -> String! {
return "id"
}
}
Is it possible to save the array in the JSON results in Realm?
Thanks.
Realm has a special RLMArray type, which allows storing a collection of RLMObject's tied to a parent RLMObject. For example, say you had the following JSON:
{
"name": "John Doe",
"aliases": [
{"alias": "John"},
{"alias": "JD"}
]
}
You could model this with the following classes:
class Alias: RLMObject {
dynamic var alias = ""
}
class Person: RLMObject {
dynamic var name = ""
dynamic var aliases = RLMArray(objectClassName: "Alias")
}
So you could simply create a Person object with the following API call:
Person.createInRealm(realm, withObject: jsonObject)
You can learn more about how RLMArrays work from Realm's reference documentation: http://realm.io/docs/cocoa/0.80.0/api/Classes/RLMArray.html