使用指针查询对象 - parse, swift2

querying an object with a pointer - parse, swift2

我有 2 个 classes,我有一个 Activity Class 和 JobPost class,在我的 Activity class 中有一个名为 "postedJob" 的对象,它是一个指针(JobPost),它存储发布的每个职位的 objectID。

我想要实现的是从 activity 查询 postedJob,但是我在表单解析下面的代码抛出错误。

let jobPostObject = PFObject(className: "JobPost")
let query = PFQuery(className: "Activity")
query.whereKey("postedJob", equalTo: jobPostObject)
let objects = query.findObjects()
print(objects)

我不明白为什么会在下面返回此错误

'Tried to save an object with a new, unsaved child.'
*** First throw call stack:
(
0   CoreFoundation                      0x0000000108213f45 __exceptionPreprocess + 165
1   libobjc.A.dylib                     0x0000000107c8bdeb objc_exception_throw + 48
2   CoreFoundation                      0x0000000108213e7d +[NSException raise:format:] + 205
3   post                            0x00000001063c5e92 -[PFPointerObjectEncoder encodeParseObject:] + 108
4   post                            0x00000001063c5324 -[PFEncoder encodeObject:] + 113
5   post                            0x00000001063948ef __129+[PFRESTQueryCommand findCommandParametersWithOrder:conditions:selectedKeys:includedKeys:limit:skip:extraOptions:tracingEnabled:]_block_invoke97 + 1808
6   CoreFoundation                      0x0000000108180cb5 __65-[__NSDictionaryI enumerateKeysAndObjectsWithOptions:usingBlock:]_block_invoke + 85
7   CoreFoundation                      0x0000000108180bbd -[__NSDictionaryI enumerateKeysAndObjectsWithOptions:usingBlock:] + 237
8   post                            0x00000001063940fd +[PFRESTQueryCommand findCommandParametersWithOrder:conditions:selectedKeys:includedKeys:limit:skip:extraOptions:tracingEnabled:] + 911
9   post                            0x0000000106393d2c +[PFRESTQueryCommand findCommandParametersForQueryState:] + 296
10  post                            0x00000001063937df +[PFRESTQueryCommand findCommandForQueryState:withSessionToken:] + 79
11  post                            0x00000001063a5739 __78-[PFQueryController findObjectsAsyncForQueryState:withCancellationToken:user:]_block_invoke + 106
12  post                            0x000000010634a7be __37+[BFTask taskFromExecutor:withBlock:]_block_invoke + 78
13  post                            0x000000010634bf20 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke_2 + 112
14  libdispatch.dylib                   0x000000010a2f1e5d _dispatch_call_block_and_release + 12
15  libdispatch.dylib                   0x000000010a31249b _dispatch_client_callout + 8
16  libdispatch.dylib                   0x000000010a2fabef _dispatch_root_queue_drain + 1829
17  libdispatch.dylib                   0x000000010a2fa4c5 _dispatch_worker_thread3 + 111
18  libsystem_pthread.dylib             0x000000010a65a4f2 _pthread_wqthread + 1129
19  libsystem_pthread.dylib             0x000000010a658375 start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

编辑 1:

Import UIKit

class ActivityEmployerVC: UITableViewController {

    var num = 0
    var postJob: String?
    var dataSource: [PFObject] = []

    //MARK: - PULL TO REFRESH FUNCTION
    func refresh(sender:AnyObject) {
        // Updating your data here...
        self.fetchDataFromParse()
        self.refreshControl?.endRefreshing()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationController?.navigationBar.barTintColor = UIColor(netHex: 0x003366)
        self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
        // Do any additional setup after loading the view.

        self.refreshControl?.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
        //self.refreshControl?.backgroundColor = UIColor(netHex: 0x003366)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    override func viewDidAppear(animated: Bool) {
        fetchDataFromParse()
    }


    //MARK: - TABLE VIEW 
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        let query = PFQuery(className: "Activity")
        let userPointer = PFUser.objectWithoutDataWithObjectId(PFUser.currentUser()?.objectId)
        query.whereKey("fromUser", equalTo: userPointer)
        let objects = query.findObjects()
        self.num = (objects?.count)!

        print(num)
        return num        

    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cellIdentifier = "Cells"
        let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier  , forIndexPath: indexPath)

        if dataSource.isEmpty{
            fetchDataFromParse()
            print("No Post")
        } else {
            if num == 0{
                cell.textLabel?.text = "Start posting a job!"
            } else {
                //MARK: - TABLEVIEW TITLE CELL
                let itemArr:PFObject = self.dataSource[indexPath.row]
                postJob = itemArr["type"] as? String
                if postJob == "jobPost"{

                    let jobPostObject = PFObject(className: "JobPost")

                    let query = PFQuery(className: "Activity")
                    query.whereKey("postedJob", equalTo: jobPostObject)
                    let objects = query.findObjects()
                    print(objects)



                    cell.textLabel?.text = "You posted a job - \(postJob!)"
                }

                //MARK: - TABLEVIEW DATE CELL
                let createdDate = itemArr.createdAt
                let form = NSDateComponentsFormatter()
                form.maximumUnitCount = 2
                form.unitsStyle = .Abbreviated // or .Full, whatever you prefer
                let d = form.stringFromTimeInterval(NSDate.timeIntervalSinceReferenceDate() - createdDate!.timeIntervalSinceReferenceDate)

                cell.detailTextLabel?.text = "\(d!) ago"
            }//end of if num

        }//end of datasource.isempty

        return cell
    }

    //MARK: - DATA FETCHING FUNCTIONS
    func fetchDataFromParse() {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in
            //MARK: - CLEARING ARRAYS
            self.dataSource.removeAll()

            //        MARK: - JOB POST QUERY
            if PFUser.currentUser()?.objectId == nil{
                PFUser.currentUser()?.saveInBackgroundWithBlock({ (success, error) -> Void in
                    let query = PFQuery(className: "Activity")
                    //creating a pointer
                    let userPointer = PFUser.objectWithoutDataWithObjectId(PFUser.currentUser()?.objectId)

                    query.whereKey("fromUser", equalTo: userPointer)

                    query.orderByDescending("createdAt")
                    let objects = query.findObjects()
                    for object in (objects as? [PFObject])!{
                        //print(object.objectId)
                        self.dataSource.append(object)
                    }//end of for loop

                })//end of saveInBackground
            } else {

                let query = PFQuery(className: "Activity")
                //creating a pointer

                let userPointer = PFUser.objectWithoutDataWithObjectId(PFUser.currentUser()?.objectId)

                query.whereKey("fromUser", equalTo: userPointer)

                query.orderByDescending("createdAt")
                query.findObjectsInBackgroundWithBlock({ (objs, error) -> Void in
                    if error == nil {
                        for obj in (objs as? [PFObject])!{
                            //print(object.objectId)
                            self.dataSource.append(obj)
                            self.tableView.reloadData()

                        }//for loop
                    }//end of error == nil
                })// end of findobjectsinbackground

                print("query executed")

            }//end of PFUser objectID == nil else clause

        })

    }


}

编辑 2:

发生这种情况是因为 jobPostObject 不是一个完整的对象,它只是一个空的、未保存的 JobPost

查询本身没有多大意义:

你先创建一个新的JobPost

let jobPostObject = PFObject(className: "JobPost")

那么您正在尝试 find 一个 Activity 关联到此 JobPost:

 query.whereKey("postedJob", equalTo: jobPostObject)

由于jobPostObject是全新的,没有数据,更重要的是,从来没有保存解析,这个请求怎么可能return什么?

就是说这个错误:

Tried to save an object with a new, unsaved child

表示您正尝试在查询中使用 的对象。脏对象是新对象,或者是已修改但尚未保存在数据库中的现有对象。


尝试添加

query.includeKey("postedJob")

毕竟你

let query = PFQuery(className: "Activity")

然后你可以替换jobPostObject部分:

let jobPostObject = PFObject(className: "JobPost")

let query = PFQuery(className: "Activity")
query.whereKey("postedJob", equalTo: jobPostObject)
let objects = query.findObjects()
print(objects) 

类似

let jobPostObject = itemArr["postedJob"] as? PFObject