I tried putting this off for as long as I could, but I'm really stuck here.
I'm trying to utilize Inverse Relationships
Basically my scheme looks like this:
class Album
var artist: artist?
class Artist
#NSManaged var albums:NSArray?
class func albumsInverseRelation() -> String { return "artist" }
class func albumsItemClass() -> AnyClass { return Album.self }
Then later I try to access the computed property, albums
bgdb.modelFactory?.registerClass("Album", forDocumentType: "Album")
bgdb.modelFactory?.registerClass("Artist", forDocumentType: "Artist")
if let artistID = artist?.document?.documentID, let fetchedArtist = try! Artist.fetchOne(field: "_id", operand: .Matches, value: artistID as AnyObject, database: bgdb) {
print(fetchedArtist.albums as! [Album])
}
But fetchedArtist.albums returns an empty array!
This is why I'm confused, from debugging:
(lldb) po album?.artist?.document?.documentID
▿ Optional<String>
- some : "-obO5dJTBF-xu4lzbWTM9yU"
(lldb) po fetchedArtist.document?.documentID
▿ Optional<String>
- some : "-obO5dJTBF-xu4lzbWTM9yU"
As it appears, there is an Album that has an Artist ID
and I can also match that Artist ID with an existing Artist
Yet when I ask the artist instance for it's albums, it fails to return the Album that has the same artist ID
Am I missing something here?
Sweet baby ...
Biggest waste of a few hours I've had in a while
in my code where I was setting the artist property
albumInstance.artist = artistInstance
it set the model, and everything seemed fine...
But I wasn't calling
albumInstance.save() right after...
So at runtime, I could see that albumInstance.artist had the right document ID, but without save(), the inverse relationship can't work.
yeah... doing that fixed everything...
Related
I developed a SwiftUI app for iPhone/iPad/Mac. The app lists my films (first view) with information such as a note of each film and if the film was seen.I have a JSON file with:
id : Int, unique identifier
nom : String, title of film
idL : String, first charachter of title
note : Int, note of each film (between 0 and 10)
isShow : Bool, indicate if the film was seen or not
I created a toggle to only display films where isShow=false, but I was unable to link this toggle with my JSON property...
Here is my project : https://github.com/thomjlg/Films-APP
JSON file : https://gist.githubusercontent.com/thomjlg/0782e9e8e27c346af3600bff9923f294/raw/9705fb0c6b40eae59578755b86e331bea257972b/films2.json
I believe when you're saving the movies you don't reload the userData.
Toggle("Film", isOn: self.$movie.isShow)
.onTapGesture {
self.userData.fetcher.save(movies: self.userData.movies)
self.movie.isShow = !self.movie.isShow
print(self.movie.isShow)
}
fetcher.save(movies:) just saves your movies but UserData is created only once and movies are loaded only in init:
window.rootViewController = UIHostingController(rootView: contentView
.environmentObject(UserData())
)
init() {
fetcher.load { (movies) in
if let movies = movies {
self.movies = movies
}
}
}
I'm trying to print the individual members of Results after parsing JSON data and assigning it to Question.
struct Question: Decodable
{
let response_code: Int
let results: [Results]
}
struct Results: Decodable
{
let category: String
let question: String
let correct_answer: String
let incorrect_answers: [String]
}
I tried using:
print(question.results)
But I get:
[Trivia_Game.Results(category: "Entertainment: Music", question: "Which of the following bands is Tom DeLonge not a part of?", correct_answer: "+44", incorrect_answers: ["Box Car Racer", "Blink-182", "Angels & Airwaves"])]
How do I access the individual members such as "category" or "question"?
You would have to first access an individual element of question.results, like so:
question.results[n] // where n represents a valid array index number
And then to access specific properties of that individual Results structure, you would do it in the same way as you would access the value of a property of any other struct. For example, if you wanted to get the value of the category member of a Results structure, you would do this:
question.results[n].category
And then if you wanted to print the value of that specific member (again, using the category member as an example), you would do this:
print(question.results[n].category)
Now, if you wanted to print out the value of the category member for each of the Results structures in the question.results array, then you could use a for loop like so:
for result in question.results {
print(result.category)
}
Hope that helps.
results is an array. You have to enumerate the array
let results = question.results
for result in results {
print(result.category, result.question)
}
or
question.results.forEach { print($0.category, $0.question) }
I am running into a peculiar issue when trying to simultaneously update values at different JSON branches in Firebase. The method provided in the documentation is perfect when it comes to creating new data,
let key = ref.child("posts").childByAutoId().key
let post = ["uid": userID,
"author": username,
"title": title,
"body": body]
let childUpdates = ["/posts/\(key)": post,
"/user-posts/\(userID)/\(key)/": post]
ref.updateChildValues(childUpdates)
but when I try to update data at multiple locations, it overwrites the other keys as if I was using setValue. Here is my code.
let userID = Auth.auth().currentUser?.uid
userRef = Database.database().reference()
let vehicle = ["make":make.text,
"model": model.text,
"year":year.text,
"color":color.text,
"doors":doors.text]
let driver = ["currentEvent":eventID]
let childUpdates = ["/users/\(userID!)": driver,
"/status/\(userID!)/driverInfo/vehicle": vehicle]
userRef.updateChildValues(childUpdates)
I have also attached a picture which shows which data is and isn't being deleted when the function is executed.
I believe what I am trying to do is possible, and from what I understand the whole purpose of updateChildValues is so that other children aren't overwritten.
Any help is appreciated. Thanks!
Currently you are updating the objects with objects like this:
let childUpdates = ["/users/\(userID!)": driver,
"/status/\(userID!)/driverInfo/vehicle": vehicle]
You are giving the object (a dictionary) as the value of the childUpdates dictionary. What this does is that replace all the children with this object meaning deleting the values for which you are sending nil for example in your case you have not included info or infoThat .
Now if you want to change only the values you want to give like only change the value of say make and model for vehicle and currentEvent for driver , you have to give the particular path for these values
["/users/\(userID!)/currentEvent": eventID,
"/status/\(userID!)/driverInfo/vehicle/make": make.text, "/status/\(userID!)/driverInfo/vehicle/model": model.text]
I think this will update the values of these locations as you expected.
HTH...
Correct me if I am mistaken, but if I understand what you're trying to do this might yield better results?
let userID = Auth.auth().currentUser?.uid
userRef = Database.database().reference()
let vehicle = ["make":make.text,
"model": model.text,
"year":year.text,
"color":color.text,
"doors":doors.text]
let driver = ["currentEvent":eventID]
let childUpdates = ["/users/": userID!),
"/status/\(userID!)/driverInfo": vehicle]
userRef.updateChildValues(childUpdates)
I develop web application with golang.
I use the library gocraft/dbr as O/R Mapper.
I have two tables: image and entry.
I join their tables and I want to get image_url.
type Image struct {
ImageUrl dbr.NullString `db:"image_url"`
}
type Entry struct {
CompanyImageID dbr.NullInt64 `db:"company_image_id"`
CompanyImage Image
EyecatchIamgeID dbr.NullInt64 `db:"eyecatch_image_id"`
EyecatchImage Image
}
Then I tried below:
var entry Entry
sess.Select("*").From("entry").
LeftJoin(dbr.I("image").As("eyecatch_image"), "entry.eyecatch_image_id = eyecatch_image.id").
LeftJoin(dbr.I("image").As("company_image"), "entry.company_image_id = company_image.id").
Load(&entry)
log.Println("company:", entry.CompanyImage)
log.Println("eyecatch:", entry.EyecatchImage)
result:
company: {{{https://company_image_url.png true}}}
eyecatch: {{{ false}}}
I expect below, but it did not become as expected.
company: {{{https://company_image_url.png true}}}
eyecatch: {{{{http://eyecatch_image_url.png true}}}
When I tried to change join condition like below:
sess.Select("*").From("entry").
LeftJoin(dbr.I("image").As("eyecatch_image"), "entry.eyecatch_image_id = eyecatch_image.id")
Load(&entry)
result:
company: {{{http://eyecatch_image_url.png true}}}
eyecatch: {{{ false}} {{ false}}}}
I don't know how to use join with multiple conditions.
Thank you.
The documentation is really poor - it seems they gave up on the idea of publishing the library. There is an open pull request that provides a little better documentation.. Here the author describes that you can create a multiple condition like this:
cond:= dbr.And(
dbr.Or(
dbr.Gt("created_at", "2015-09-10"),
dbr.Lte("created_at", "2015-09-11"),
),
dbr.Eq("title", "hello world"),
)
Then use the condition in any statement:
sess.Select("*").From("entry").
LeftJoin(dbr.I("image").As("eyecatch_image"), cond)
Load(&entry)
lets say I have a JSON/object literal like so:
var animals = {
dogs : {
breed : 'breed name'
weight : 'fat'
},
cats : {
breed : 'breed name'
weight : 'fat'
}
}
because dogs and cats are the same, is there a way to abstract that key? So for example if you were doing a loop on animals, how would you have a single loop and get to breed and weight of dogs and cats with out actually using dogs and cats? The JSON I have goes a couple levels deeper than this before this happens.
Thanks for any help!
Yes it is possible. You can loop over the keys of the object.
for(var animalName in animals) {
currentAnimal=animals[animalName];
console.log(animalName,currentAnimal);
}
That will loop through all your animals and print the name and the associated object.
Just FYI: Your JSON is invalid, you need to add commas between the properties