Am I Querying and Subclassing Correctly? - ios

Below is my code that I am using to query for an object from Parse:
func findEmployeeForLoggedInUser(completion: (array: [AnyObject], error: String?) -> Void) {
var query = PFQuery(className: "Employee")
query.whereKey("employerId", equalTo: PFUser.currentUser()!.objectId!)
query.findObjectsInBackgroundWithBlock { (results, error) -> Void in
println(results)
var employeeArray = results
if let error = error {
let errorString = error.userInfo?["error"] as? String
if let objects = employeeArray {
completion(array: objects, error: errorString)
} else {
completion(array: [], error: errorString)
}
} else {
completion(array: employeeArray!, error: nil)
}
}
}
Below is the code where the subclass of PFObject was declared:
class PFEmployee: PFObject, PFSubclassing {
override class func initialize() {
self.registerSubclass()
}
class func parseClassName() -> String {
return "Employee"
}
#NSManaged var name: String
#NSManaged var jobDesc: String
#NSManaged var numberOfPoints: Int
#NSManaged var education: String
#NSManaged var birthday: String
#NSManaged var employerId: String
#NSManaged var profilePicture: PFFile?
#NSManaged var email: String
#NSManaged var commentary: String
}
My app is crashing, and I suspect it has something to do with this. Am I doing all of this correctly?

Use this crash free code...
var stuffarray = [String]()
var query = PFQuery(className:"ClassName")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
println("Successfully retrieved \(objects!.count) scores.")
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
stuffarray.append(object.valueForKey("Column")! as! String)
}
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
dispatch_async(dispatch_get_main_queue()) {
self.alert("\(stuffarray)", Message: "")
}
}

Related

"RLMArray has been invalidated or the containing object has been deleted." error

Im trying to delete a realm object which contains a realm list of objects, but when I do that I receive this error: "Thread 1: RLMArray has been invalidated or the containing object has been deleted.". I've tried all the solutions I've managed to find but none of them helped me to fix my issue. Thank you for helping in advance!
Parent object creation code :
#MainActor
func addWordSet(name : String){
Task {
do {
// let realm = try await realmService.getRealm()
if let realm = realmService.getRealm() {
let user = realmService.getCurrentUser()
let set = WordSet(name: name, ownerId: user?.id ?? "")
try realm.write {
realm.add(set, update: Realm.UpdatePolicy.modified)
}
}
}catch {
print(error)
}
}
}
Child object creation code
#MainActor
func addTranslationToSet(set : WordSet, term : String, meaning : String, completion: #escaping () -> Void){
Task {
do {
if let realm = realmService.getRealm() {
let user = realmService.getCurrentUser()
let translation = Translation(word: term, translation: meaning, ownerId: user?.id ?? "")
try realm.write {
set.translations.append(translation)
}
completion()
}
}catch {
print(error)
}
}
}
Parent object deletion code:
#MainActor
func deleteWordSet(set : WordSet){
Task {
do {
if let realm = realmService.getRealm() {
try realm.write {
realm.delete(set)
}
}
} catch{
print(error)
}
}
}
#MainActor
func deleteTranslationFromSet(set : WordSet, translation : Translation, completion: #escaping () -> Void){
Task {
do {
if let realm = realmService.getRealm() {
let index = set.translations.firstIndex{
$0._id == translation._id
}
try realm.write {
if let index = index {
set.translations.remove(at: index)
}
}
completion()
}
}catch {
print(error)
}
}
models code :
class Translation : Object {
#Persisted(primaryKey: true) var _id : ObjectId
#Persisted var owner_id : String
#Persisted var word : String
#Persisted var translation : String
convenience init(word : String, translation: String, ownerId: String){
self.init()
self.word = word
self.translation = translation
self.owner_id = ownerId
}
}
class WordSet : Object {
#Persisted var name : String
#Persisted(primaryKey: true) var _id : ObjectId
#Persisted var owner_id : String
#Persisted var translations : List<Translation>
convenience init(name : String, ownerId : String){
self.init()
self.name = name
self.owner_id = ownerId
}
}

Cannot return items in a string array

I'm very new to Parse and Swift and I have this project I am working on and I am trying to create a search bar that displays all the items from the key "names" from my Parse database.
I have created this function that is supposed to take all the names and return them in a string array. But instead, the array never gets filled and all I get as a return is [].
class Offices {
var name: String
var phone: String
var location: String
init(name: String = "def_name", phone: String = "def_phone", location: String = "def_location") {
self.name = name
self.phone = phone
self.location = location
}
func retrieveName() -> [String] {
var models = [String]()
let queries = PFQuery(className: "Directory")
queries.findObjectsInBackground { (object, error) in
if let error = error {
// The query failed
print(error.localizedDescription)
} else if let object = object {
// The query succeeded with a matching result
for i in object{
models.append(i["name"] as? String ?? self.name)
}
} else {
// The query succeeded but no matching result was found
}
}
return models
}
findObjectsInBackground method is asynchronous. So you should change retrieveName function as below:
class Offices {
var name: String
var phone: String
var location: String
init(name: String = "def_name", phone: String = "def_phone", location: String = "def_location") {
self.name = name
self.phone = phone
self.location = location
// I call retrieveName here for example. You can call it where you want.
retrieveName() { (success, models) in
if success {
print(models)
} else {
print("unsuceess")
}
}
}
func retrieveName(completion: #escaping (_ success: Bool, _ models: [String]) -> Void) {
var models = [String]()
let queries = PFQuery(className: "Directory")
queries.findObjectsInBackground { (object, error) in
if let error = error {
// The query failed
print(error.localizedDescription)
completion(false, [])
} else if let object = object {
// The query succeeded with a matching result
for i in object{
models.append(i["name"] as? String ?? self.name)
}
completion(true, models)
} else {
completion(true, [])
// The query succeeded but no matching result was found
}
}
}
}

Trying to load data from Parse however I keep receiving the error EXC_Brekapoint whenever I try to compile the app

I am currently trying to load data from Parse (which I realize will soon be obselete but I have to stay on it for now) and I have a custom class that is to handle all the data from the backend like so:
import Foundation
import Parse
class FeedContent: PFObject {
#NSManaged var address: String
#NSManaged var content: PFFile
#NSManaged var isVideo: Int
#NSManaged var attendeeObjectId: String
#NSManaged var created: NSDate?
#NSManaged var objId: String
init(address: String, content: PFFile, isVideo: Int, attendeeObjectId: String, created: NSDate?, objId: String) {
super.init()
self.address = address
self.content = content
self.isVideo = isVideo
self.attendeeObjectId = attendeeObjectId
self.created = createdAt
self.objId = objId
}
override init() {
super.init()
}
}
extension FeedContent: PFSubclassing {
class func parseClassName() -> String {
return "FeedContent"
}
override class func initialize() {
var onceToken: dispatch_once_t = 0
dispatch_once(&onceToken) {
self.registerSubclass()
}
}
}
and in my Display View Controller I am creating an array to house these items then calling a function to display the data , like here:
func addPFObjectInFeedContent(object : PFObject) {
let newItem = FeedContent()
newItem.address = (object["address"] as? String)!
newItem.isVideo = (object["isVideo"] as? Int)!
newItem.attendeeObjectId = (object["attendeeObjectId"] as? String)!
//newItem.eventObjectId = (object["eventObjectId"] as? String)!
newItem.content = (object["content"] as? PFFile)!
newItem.created = object.createdAt
newItem.objId = object.objectId!
self.feedContentItems.append(newItem)
}
Here is the array as well:
var feedContentItems = [FeedContent]()
On this line specifically is where the EXC_Breakpoint error occurs:
newItem.isVideo = (object["isVideo"] as? Int)!
so i was curious if anyone had any intimation of what may be happening?
func loadParseFeed() {
let contentQuery = PFQuery(className: "FeedContent")
contentQuery.whereKey("address", equalTo: defaults.objectForKey("newLocation")! as! String)
//contentQuery.whereKey("flagged", notEqualTo: true)
contentQuery.orderByDescending("createdAt")
if blacklist.count != 0 {
for var item = 0; item <= blacklist.count; item += 1 {
contentQuery.whereKey("attendeeObjectId", equalTo: blacklist[item])
}
}
contentQuery.findObjectsInBackgroundWithBlock({ (objects:[PFObject]?,error: NSError?) -> Void in
if error == nil {
if let object = objects as [PFObject]? {
if objects!.count > 0 {
for thing in objects! {
// let newItem = FeedContent()
// newItem.isVideo = (thing["isVideo"] as? Int)!
// newItem.attendeeObjectId = (thing["attendeeObjectId"] as? String)!
// newItem.eventObjectId = (thing["eventObjectId"] as? String)!
// newItem.content = (thing["content"] as? PFFile)!
// newItem.created = thing.createdAt
// newItem.objId = thing.objectId!
// self.feedContentItems.append(newItem)
self.addPFObjectInFeedContent(thing)
}
self.advanceFeed()
// self.overviewTimer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "advanceFeed", userInfo: nil, repeats: true)
// self.overviewTimer.fire()
}
}
}
})
}

PFObject subclassing and pointers

I have a class UserFeed where I store all the posts. And I have a class UserProfile where I store all the user details(name, age, occupation). Currently I have a pointer to UserProfile. But when I try to set the occupationLabel it gives me nil.
// PostsCollectionViewCell.swift
import UIKit
import DateTools
import Parse
class PostsCollectionViewCell: UICollectionViewCell {
var post: Post! {
didSet {
updateUI()
}
}
#IBOutlet var postLabel: UILabel!
#IBOutlet var genderLabel: UILabel!
#IBOutlet var occupationLabel: UILabel!
#IBOutlet var timeLabel: UILabel!
#IBOutlet var likeButton: UIButton!
func layoutSubview() {
super.layoutSubviews()
}
private func updateUI() {
occupationLabel?.text! = post.userProfile.occupation
timeLabel?.text! = post.createdAt?.shortTimeAgoSinceDate(NSDate()) ?? ""
postLabel?.text! = post.postText
}
#IBAction func likeButtonDidTouch(sender: AnyObject) {
}
}
Post query in my DiscoverViewController
func queryForPosts() {
PFGeoPoint.geoPointForCurrentLocationInBackground { (geopoint, error) in
if !(error != nil) {
if let geoPoint = geopoint {
let query = PFQuery(className: "UserFeed")
query.whereKey("location", nearGeoPoint: geoPoint, withinMiles: 5)
query.addDescendingOrder("createdAt")
query.includeKey("userProfile")
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if error == nil {
if let postObjects = objects as? [PFObject] {
self.posts.removeAll()
for postObject in postObjects {
let post = postObject as! Post
self.posts.append(post)
}
self.collectionView.reloadData()
}
} else {
print("\(error!.localizedDescription)")
}
})
}
}
}
}
Post subclassing
import UIKit
import Parse
public class Post: PFObject, PFSubclassing{
// MARK: - Public API
#NSManaged public var username: PFUser
#NSManaged public var location: PFGeoPoint?
#NSManaged public var userProfile: String!
#NSManaged public var postText: String!
#NSManaged public var numberOfLikes: Int
#NSManaged public var likedUserIdCollection: [String]!
public func incrementNumberOfLikes() {
numberOfLikes++
self.saveInBackground()
}
//Mark: - Convience init
init(username: PFUser, location: PFGeoPoint?, userProfile: String, postText: String, numberOfLikes: Int) {
super.init()
self.username = username
self.location = location
self.userProfile = userProfile
self.postText = postText
self.numberOfLikes = numberOfLikes
self.likedUserIdCollection = [String]()
}
override init() {
super.init()
}
//MARK: - Like / Dislike
public func like(){
let currentUserObjectId = PFUser.currentUser()!.objectId!
if !likedUserIdCollection.contains(currentUserObjectId) {
numberOfLikes++
likedUserIdCollection.insert(currentUserObjectId, atIndex: 0)
self.saveInBackground()
}
}
public func dislike() {
let currentUserObjectId = PFUser.currentUser()!.objectId!
if likedUserIdCollection.contains(currentUserObjectId) {
numberOfLikes--
for (index, userId) in likedUserIdCollection.enumerate() {
if userId == currentUserObjectId {
likedUserIdCollection.removeAtIndex(index)
break
}
}
self.saveInBackground()
}
}
// MARK: - PFSubClassing
override public class func initialize() {
struct Static {
static var onceToken : dispatch_once_t = 0;
}
dispatch_once(&Static.onceToken) {
self.registerSubclass()
}
}
public static func parseClassName() -> String {
return "UserFeed"
}
}
Object can't store value until it intialize, need to call below init as present in your code
init(username: PFUser, location: PFGeoPoint?, userProfile: String, postText: String, numberOfLikes: Int) {
super.init()
self.username = username
self.location = location
self.userProfile = userProfile
self.postText = postText
self.numberOfLikes = numberOfLikes
self.likedUserIdCollection = [String]()
}
Need to initialize Post object, seems you have not made it.

Parse PFSubclassing in Swift of Object type

I'm pretty new to iOS/Swift/Parse and I'm trying to build a model of a class using PFSubclassing.
The data I'm trying to represent should look something like this
{
text: ""
location : {
name: "",
longitude: "",
latitude: ""
}
}
So fare the model I'm have is
class LocationModel {
var name: String?
var longitude: Float?
var latitude: Float?
}
class PostModel: PFObject, PFSubclassing {
class func parseClassName() -> String! {
return "Post"
}
#NSManaged var text: String?
var location: LocationModel?
}
The test property is being saved successfully but I'm unable to get the location properties to save.
The code I'm using to save a record to parse is
var test = PostModel()
test.location?.name = "ESB"
test.location?.latitude = 1
test.location?.longitude = 1
test.text = "This is a test post to see if this works!"
test.saveEventually { (success: Bool, error: NSError!) -> Void in
println(error)
println(success)
}
I did a lot of digging online but I'm unable to find a solution on how to represent an Object datatype in Swift using Parse PFSubclassing
Any help would be greatly appreciated.
Thank you
Here's my solution:
I will create a Hero object for example.
class Hero: PFObject, PFSubclassing {
#NSManaged var strengthPoint: Double
#NSManaged var name: String
static func parseClassName() -> String {
return "Hero"
}
init(strengthPoint: Double, name: String) {
super.init()
self.strengthPoint = strengthPoint
self.name = name
}
init(pfObject: PFObject) {
super.init()
self.strengthPoint = pfObject.object(forKey: "strengthPoint") as! Double
self.name = pfObject.object(forKey: "name") as! String
}
override init() {
super.init()
}
override class func query() -> PFQuery<PFObject>? {
let query = PFQuery(className: self.parseClassName())
query.order(byDescending: "createdAt")
query.cachePolicy = .networkOnly
return query
}
}
Now, after defining your model, you can use these methods to store and retrieve
Create your object in server
func createHero() {
let hero = Hero(strengthPoint: 2.5, name: "Superman")
hero.saveInBackground { (isSuccessful, error) in
print(error?.localizedDescription ?? "Success")
}
}
Retrieve object from server
func retrieveHero() {
let query = Hero.query()
query?.getFirstObjectInBackground(block: { (object, error) in
if error != nil {
print(error?.localizedDescription ?? "Something's wrong here")
} else if let object = object {
let hero = Hero(pfObject: object)
print(hero.strengthPoint) // 2.5
print(hero.name) // Superman
}
})
}
I have seen several different methods for PFSubclassing in Swift 1.2, but the following works best for me:
To begin with, make sure that you have the following in your Objective-C Bridging Header:
#import <Parse/PFObject+Subclass.h>
Here is a very basic example of subclassing PFObject:
import Foundation
import Parse
class Car: PFObject, PFSubclassing {
override class func initialize() {
self.registerSubclass()
}
static func parseClassName() -> String {
return "Car"
}
#NSManaged var model: String
#NSManaged var color: String
#NSManaged var yearManufactured: Int
}
So in your case, this would be:
class PostModel: PFObject, PFSubclassing {
override class func initialize() {
self.registerSubclass()
}
static func parseClassName() -> String {
return "Post"
}
#NSManaged var text: String?
}
Concerning your LocationModel...I'm a bit confused as to what exactly you are trying to accomplish with that. I hope this helps.

Resources