Realm is returning an empty object when I convert it to an array - xcode

Using Realm in a Swift application. I'm fetching users from Realm and want to return an array of users (as my app also uses Parse, it's easier if they are all arrays I'm guessing).
Here is my code:
class func fetchUsersFromDB() -> [User]{
var users = [User]()
let realm = Realm()
var allUsers = realm.objects(User)
users = Array(allUsers)
return users
}
When I do a dump of allUsers I can see a Realm result. But when I dump users it shows me the object with default values.
Any ideas what I'm doing wrong?
Here is how I declare the User model
class User: Object {
dynamic var objectId: String = ""
dynamic var username: String = ""
dynamic var password: String = ""
dynamic var emailVerified: Bool = false
dynamic var email: String = ""
dynamic var firstName: String = ""
dynamic var defaultRelationshipId: String = ""
dynamic var picture: NSData = NSData()
dynamic var updatedAt: NSDate = NSDate()
dynamic var createdAd: NSDate = NSDate()
override static func primaryKey() -> String? {
return "objectId"
}
}

Related

Filtering String from Firestore database sends an error on SwiftUI

I'm working on implementing a search for a movies database stored in firestore using SwiftUI. I've tried doing filtering the movie names by the entered text as follows:
#ObservedObject var movies = getMoviesData()
...
ForEach(self.movies.datas) { movies in
ForEach(movies.title.filter({"\($0)".contains(searchText.lowercased()) || searchText.isEmpty})) { item in
if let url = URL(string: movies.img) {
AnimatedImage(url: url)
.resizable()
.frame(width: bounds.size.width / 2 - 0.6, height: bounds.size.height / 2 - 0.2)
}
}
.animation(.spring())
}
...
struct movies : Identifiable {
var id: String
var title: String
var img: String
var video: String
var description: String
var genre: String
}
class getMoviesData : ObservableObject{
#Published var datas = [movies]()
private var db = Firestore.firestore()
func fetchData(){
db.collection("movies").addSnapshotListener{ (querySnapshot, error) in
guard let mov = querySnapshot?.documents else{
print("No movies")
return
}
self.datas = mov.map{(queryDocumentSnapshot) -> movies in
let data = queryDocumentSnapshot.data()
let id = data["id"] as? String ?? ""
let title = data["title"] as? String ?? ""
let img = data["img"] as? String ?? ""
let video = data["video"] as? String ?? ""
let description = data["description"] as? String ?? ""
let genre = data["genre"] as? String ?? ""
return movies(id: id, title: title, img: img, video: video, description: description, genre: genre)
}
}
}
}
However, I'm receiving the following error on the second ForEach statement:
Referencing initializer 'init(_:content:)' on 'ForEach' requires that 'String.Element' (aka 'Character') conform to 'Identifiable'
Movies.title represents a String output of each movie identified in the ForEach statement. How should I filter movies.title against the provided search text without invoking this error?
I am little confused about your use of variable names.
ForEach(movies.title.filter({"\($0)".contains(searchText.lowercased()) || searchText.isEmpty})) { item in
}
}
In the above code movies.title is very misleading. Is there a title property on movies array. If you need to filter, you can perhaps check out the sample code below:
struct Movie {
let title: String
}
let movies = [Movie(title: "Spiderman"), Movie(title: "Batman"), Movie(title: "Superman")]
let searchWord = "batman"
let filteredMovies = movies.filter { movie in
return movie.title.lowercased().contains(searchWord.lowercased())
}
print(filteredMovies)

how to parse json with alamofire and swiftjson?

I'm using swiftjson and alamofire to parse the json.pls help fix my code.
here the json array
Below are my code
RestClient.sharedClient.getUserWallet(uid: uid!, token: token!) { (json, error) in
print(json as Any)
self.tableRows = json!["data"].count
//ALL BELOW IS DONE BY SWIFTYJSON
let jsonArray = json?["data"].array
if jsonArray != nil {
for object in jsonArray! {
let walletCells: UserWalletCells = UserWalletCells(json: object)
self.userWalletCells.append(walletCells)
}
}
class PackageList {
var id: Int?
var user_id: String?
var amount: Int?
var currency_id: Int?
var release_rate: Double?
var release_per_day: Int?
var release_date: String?
var end_date: String?
var total_release: Int?
var tier_id: Int?
var is_active: Int?
var created: String?
var modified: String?
var remainingdays: Int?
init(json: JSON){
self.id = json["id"].intValue
self.user_id = json["user_id"].stringValue
self.amount = json["amount"].intValue
self.currency_id = json["currency_id"].intValue
self.release_rate = json["release_rate"].doubleValue
self.release_per_day = json["release_per_day"].intValue
self.release_date = json["release_date"].stringValue
self.end_date = json["end_date"].stringValue
self.total_release = json["total_release"].intValue
self.tier_id = json["tier_id"].intValue
self.is_active = json["is_active"].intValue
self.created = json["created"].stringValue
self.modified = json["modified"].stringValue
self.remainingdays = json["remainingdays"].intValue
}
}
I'm using swiftjson and alamofire to parse the json.pls help fix my code.
Please try this it will help you
let json = JSON(response)
let dictResult = json["data"].dictionaryValue
let arrayValue = dictResult["apckage"].arrayValue
var arrList = [PackageList]()
for i in 0..<arrayValue.count{
let packageList = PackageList()
let dictRespose = arrayValue[i]
packageList. id = dictRespose["id"].stringValue
packageList. user_id = dictRespose["user_id"].stringValue
packageList. amount = dictRespose["amount"].stringValue
arrList.append(packageList)
}
return arrTaxLis
Like this you put all your key. It may helps you. Thank you.

Reorder UicollectioView items using RealmSwift on drag and drop

I'm Trying reorder UICollectionViewcell Images on drag and drop using RealmSwift As database, My UI is not updating on a drag and drop and strange behaviour, some Images are duplicating , my code is Like this
RealmModel As
class StoryAlbumDM: Object {
dynamic var id = 0
dynamic var type = ""
dynamic var isImage: Int = 0
dynamic var textData = ""
dynamic var imageData: NSData? = nil
dynamic var rowId: Int = 0
dynamic var position: Int = 0
dynamic var storyId: Int = 0
dynamic var isCoverImage: Int = 0
dynamic var imagePath = ""
let allStories = List<StoryAlbumDM>()
}
On drag and drop I'm doing Like this
func collectionView(collectionView: UICollectionView, atIndexPath: NSIndexPath, didMoveToIndexPath toIndexPath: NSIndexPath) {
print("moveItemAtIndexPath")
let fromIndexPath: Int = atIndexPath.row
print("from", fromIndexPath)
let toIndexPathInt: Int = toIndexPath.row
print("To", toIndexPath)
let fromData: StoryAlbumDM!
fromData = realm.objects(StoryAlbumDM.self).filter("position = %d AND storyId = %d", fromIndexPath, self.storyID).first!
let toData: StoryAlbumDM!
toData = realm.objects(StoryAlbumDM.self).filter("position = %d AND storyId = %d", toIndexPath, self.storyID).first!
var tempData = StoryAlbumDM()
self.performSelectorOnMainThread(#selector(StoryViewController.updateSrtoryInRealm), withObject: self.collectionView, waitUntilDone: true)
dispatch_async(dispatch_get_main_queue(), {
self.collectionView.performBatchUpdates({
self.collectionView.reloadData()
}, completion: nil)
})
}
func updateSrtoryInRealm() {
self.tempData.type = self.toData.type
self.tempData.isImage = self.toData.isImage
self.tempData.textData = self.toData.textData
self.tempData.rowId = self.toData.rowId
self.tempData.imageData = self.toData.imageData
self.tempData.position = self.toData.position
self.tempData.storyId = self.toData.storyId
self.tempData.isCoverImage = self.toData.isCoverImage
self.tempData.imagePath = self.toData.imagePath
do {
try! realm.write {
self.toData.type = self.fromData.type
self.toData.isImage = self.fromData.isImage
self.toData.textData = self.fromData.textData
self.toData.rowId = self.fromData.rowId
self.toData.imageData = self.fromData.imageData
self.toData.position = self.fromData.position
self.toData.storyId = self.fromData.storyId
self.toData.isCoverImage = self.fromData.isCoverImage
self.toData.imagePath = self.fromData.imagePath
// title.id = temp.id
self.fromData.type = self.tempData.type
self.fromData.isImage = self.tempData.isImage
self.fromData.textData = self.tempData.textData
self.fromData.rowId = self.tempData.rowId
self.fromData.imageData = self.tempData.imageData
self.fromData.position = self.tempData.position
self.fromData.storyId = self.tempData.storyId
self.fromData.isCoverImage = self.tempData.isCoverImage
self.fromData.imagePath = self.tempData.imagePath
}
//}
}
catch {
print("Printed error : ")
}
Problem: Images Are duplicating, Not updating on UI , Reorder strange behaviour, please help me on this
I answered a similar question recently, but I'll re-explain it here. :)
Easily, the best and quickest way to re-order Realm objects inside a Realm file is to make an overarching List object that holds all of the Realm objects of a given type.
For example in this case, you make another object to hold that allStories value you already created:
// Model class that manages the ordering of story album objects
class StoryAlbumDMList: Object {
let allStories = List<StoryAlbumDM>()
}
// Model class for the actual story album objects
class StoryAlbumDM: Object {
dynamic var id = 0
dynamic var type = ""
dynamic var isImage: Int = 0
dynamic var textData = ""
dynamic var imageData: NSData? = nil
dynamic var rowId: Int = 0
dynamic var position: Int = 0
dynamic var storyId: Int = 0
dynamic var isCoverImage: Int = 0
dynamic var imagePath = ""
}
This way, when you want to re-order the list, all you need to do is re-order them inside this array.
Like I said in the other question, one other way you can do it (Which is not as good, but also doesn't require an extra Realm object) is to add another property named orderedIndex, which simply contains a number indicating the numerical order of these objects. When you want to re-order them, it's simply a matter of re-setting these numbers.
Let me know if you need any more clarification!

Casting NSManagedObject property from num to Bool in swift

I know that question has been asked many times, but the solutions didn't work with me. I have the following NSManaged object class:
#NSManaged var cellColor: AnyObject
#NSManaged var des: String
#NSManaged var name: String
#NSManaged var switcher: NSNumber
And when trying to assign this value to a var as a bool when loading the managed object, I get an error. This is an example of assigning the value to a var:
func loadData(){
var appDel = UIApplication.sharedApplication().delegate as AppDelegate
var context = appDel.managedObjectContext!
var request = NSFetchRequest(entityName: "Row")
var result:NSArray = context.executeFetchRequest(request, error: nil)!
if result.count > 0 {
for i in result{
var name = i.name as String
var des = i.des as String
var color = i.cellColor as UIColor
var switcher:Bool{
get{
return i.switcher == NSNumber(bool: true)
//the problem happens here
However, when I try a simple example of casting in this way, It works well.
How to solve that ??
I think it just like this:
for i in results {
var name = i.name as String
var des = i.des as String
var color = i.cellColor as UIColor
var switcher: Bool {
return Bool(i.switcher)
}
}
Didn't test that though.

How to wait for a background function to finish before calling another one in swift?

I will try to explain briefly what the situation is.
I am building a quiz app and I wanted it to work mainly using the internet, but also to work for a while when the user is disconnected. The older code I was using was made only with synchronous queries, it was taking more time than what I expected. So i decided to reformulate it.
The situation I projected is the following:
When my user selects a subject the app will synchronously get 1 question for each subsubject in order to be ready for my user click and to be faster.
After getting this first question, the app would then get another 4 (or how much is needed to complete 5) for each of the subsubjects asynchronously, while the user is occupied answering the first question that was presented to him.
Finally, the app would save the objects in the local datastore, so that the user can answer 5 questions for each subsubject when he is not connected.
Here is my code:
func getQuestionsRemotelyandSave (subsubject:String?, subject:String?, arrayOfSubsubjects:[String]?) {
self.getFromUserDefaults()
if Reachability.isConnectedToNetwork() == true {
if self.needsToGetQuestions == true {
let user = PFUser.currentUser()
var query = PFQuery(className: "Questions")
query.whereKey("answeredBy", equalTo: user)
query.whereKey("grade", equalTo: user["grade"])
if subsubject != nil && subject == nil {
query.whereKey("subsubject", equalTo: subsubject)
query.limit = 2
let array = query.findObjects()
for item in array {
let object = item as PFObject
var QuestionToPin = PFObject(className: "Questions")
QuestionToPin["Question"] = object["Question"] as String
QuestionToPin["rightAnswer"] = object ["rightAnswer"] as String
QuestionToPin["wrongAnswer1"] = object ["wrongAnswer1"] as String
QuestionToPin["wrongAnswer2"] = object ["wrongAnswer2"] as String
QuestionToPin["wrongAnswer3"] = object ["wrongAnswer3"] as String
QuestionToPin["grade"] = object["grade"] as String
QuestionToPin["subject"] = object ["subject"] as String
QuestionToPin["subsubject"] = object ["subsubject"] as String
QuestionToPin["feedback"] = object ["feedback"] as? String
QuestionToPin["shortFeedback1"] = object ["shortFeedback1"] as? String
QuestionToPin["shortFeedback2"] = object ["shortFeedback2"] as? String
QuestionToPin["shortFeedback3"] = object ["shortFeedback3"] as? String
QuestionToPin.pin()
}
query.limit = 3
query.findObjectsInBackgroundWithBlock({ (objects:[AnyObject]!, error:NSError!) -> Void in
if error == nil {
let questions = objects as [PFObject]
var QuestionsToPin = [PFObject]()
for object in questions {
var QuestionToPin = PFObject(className: "Questions")
QuestionToPin["Question"] = object["Question"] as String
QuestionToPin["rightAnswer"] = object ["rightAnswer"] as String
QuestionToPin["wrongAnswer1"] = object ["wrongAnswer1"] as String
QuestionToPin["wrongAnswer2"] = object ["wrongAnswer2"] as String
QuestionToPin["wrongAnswer3"] = object ["wrongAnswer3"] as String
QuestionToPin["grade"] = object["grade"] as String
QuestionToPin["subject"] = object ["subject"] as String
QuestionToPin["subsubject"] = object ["subsubject"] as String
QuestionToPin["feedback"] = object ["feedback"] as? String
QuestionToPin["shortFeedback1"] = object ["shortFeedback1"] as? String
QuestionToPin["shortFeedback2"] = object ["shortFeedback2"] as? String
QuestionToPin["shortFeedback3"] = object ["shortFeedback3"] as? String
QuestionToPin.pinInBackground()
}
}
})
}
if subsubject == nil && subject != nil {
var firstTime = true
var semaphore = dispatch_semaphore_create(0)
query.limit = 1
for item in arrayOfSubsubjects! {
if item != "Todas as matérias" {
var query3 = PFQuery(className: "Questions")
query3.fromLocalDatastore()
query3.whereKey("subsubject", equalTo: item)
let count = query3.countObjects()
if count == 0 {
query.whereKey("subsubject", equalTo: item)
let array:NSArray = query.findObjects()
for item in array {
let object = item as PFObject
var QuestionToPin = PFObject(className: "Questions")
QuestionToPin["Question"] = object["Question"] as String
QuestionToPin["rightAnswer"] = object ["rightAnswer"] as String
QuestionToPin["wrongAnswer1"] = object ["wrongAnswer1"] as String
QuestionToPin["wrongAnswer2"] = object ["wrongAnswer2"] as String
QuestionToPin["wrongAnswer3"] = object ["wrongAnswer3"] as String
QuestionToPin["grade"] = object["grade"] as String
QuestionToPin["subject"] = object ["subject"] as String
QuestionToPin["subsubject"] = object ["subsubject"] as String
QuestionToPin["feedback"] = object ["feedback"] as? String
QuestionToPin["shortFeedback1"] = object ["shortFeedback1"] as? String
QuestionToPin["shortFeedback2"] = object ["shortFeedback2"] as? String
QuestionToPin["shortFeedback3"] = object ["shortFeedback3"] as? String
QuestionToPin.pin()
}
}
if count > 0 {
var limit = 5 - count
if limit < 0 {
limit = 0
}
query.limit = limit
if firstTime == false {
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
}
query.findObjectsInBackgroundWithBlock({ (objects:[AnyObject]!, error:NSError?) -> Void in
if error == nil {
let questions = objects as [PFObject]
for object in questions {
var QuestionToPin = PFObject(className: "Questions")
QuestionToPin["Question"] = object["Question"] as String
QuestionToPin["rightAnswer"] = object ["rightAnswer"] as String
QuestionToPin["wrongAnswer1"] = object ["wrongAnswer1"] as String
QuestionToPin["wrongAnswer2"] = object ["wrongAnswer2"] as String
QuestionToPin["wrongAnswer3"] = object ["wrongAnswer3"] as String
QuestionToPin["grade"] = object["grade"] as String
QuestionToPin["subject"] = object ["subject"] as String
QuestionToPin["subsubject"] = object ["subsubject"] as String
QuestionToPin["feedback"] = object ["feedback"] as? String
QuestionToPin["shortFeedback1"] = object ["shortFeedback1"] as? String
QuestionToPin["shortFeedback2"] = object ["shortFeedback2"] as? String
QuestionToPin["shortFeedback3"] = object ["shortFeedback3"] as? String
QuestionToPin.pinInBackground()
}
dispatch_semaphore_signal(semaphore)
firstTime = false
}
})
}
}
}
}
}
}
}
The problem I'm facing is that I cant request multiple asynchronous functions from Parse. What I thought was maybe waiting for an asynchronous function to finish before the other one starts, but I wanted it to happen without the user having to wait. Is there a way of doing it?
Thank you.

Resources