querying an object with a pointer - parse, swift2 - parse-platform

I have 2 classes, I have an Activity Class and JobPost class, in my Activity class there is an object called "postedJob" which is a pointer(JobPost), it stores the objectID of every job posted.
What I am trying to achieve is to query the postedJob from activity, but my code below form parse is throwing an error.
let jobPostObject = PFObject(className: "JobPost")
let query = PFQuery(className: "Activity")
query.whereKey("postedJob", equalTo: jobPostObject)
let objects = query.findObjects()
print(objects)
I dont understand why it's returning this error below
'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)
Edit 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
})
}
}
EDIT 2:

This is happening because jobPostObject is not a complete object, it's just an empty, unsaved JobPost.
The query itself doesn't make a lot of sense:
You first create a new JobPost
let jobPostObject = PFObject(className: "JobPost")
Then you are trying to find an Activity associated to this JobPost:
query.whereKey("postedJob", equalTo: jobPostObject)
Since jobPostObject is brand new, has no data, and more importantly, has never been saved to parse, how could this request return anything?
That's being said this error:
Tried to save an object with a new, unsaved child
means that you are trying to use an object that is dirty in a query. A dirty object is an object that is new OR is an existing object that has been modified, but that hasn't been saved in the database.
Try to add
query.includeKey("postedJob")
after all your
let query = PFQuery(className: "Activity")
then you can replace the jobPostObject part:
let jobPostObject = PFObject(className: "JobPost")
let query = PFQuery(className: "Activity")
query.whereKey("postedJob", equalTo: jobPostObject)
let objects = query.findObjects()
print(objects)
by something like
let jobPostObject = itemArr["postedJob"] as? PFObject

Related

How to retrieve data from VCard using swift

I'm working on QR code scanning. Using the following swift code, the data in the QR code is getting printed in the console.
import UIKit
import AVFoundation
class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate
{
let session = AVCaptureSession()
#IBOutlet weak var square: UIImageView!
var video = AVCaptureVideoPreviewLayer()
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
if metadataObjects != nil && metadataObjects.count != 0
{
if let object = metadataObjects[0] as? AVMetadataMachineReadableCodeObject
{
if object.type == AVMetadataObjectTypeQRCode
{
print(object.stringValue)
let alert = UIAlertController(title: "QR Code", message: object.stringValue, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Okey", style: .default, handler: nil))
/* alert.addAction(UIAlertAction(title: "Copy", style: .default, handler: { (nil) in
UIPasteboard.general.string = object.stringValue
}))
*/
present(alert, animated: true, completion: nil)
if metadataObjects.count > 0
{
print("-------------------------------------------------")
self.session.stopRunning()
}
}
}
}
}
#IBAction func startButton(_ sender: Any)
{
// Creating session
// let session = AVCaptureSession()
// Define capture device
let captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
do {
let input = try AVCaptureDeviceInput(device: captureDevice)
session.addInput(input)
} catch {
print("Error")
}
let output = AVCaptureMetadataOutput()
session.addOutput(output)
output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
output.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
video = AVCaptureVideoPreviewLayer(session: session)
video.frame = view.layer.bounds
view.layer.addSublayer(video)
self.view.bringSubview(toFront: square)
session.startRunning()
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
OUTPUT:
BEGIN:VCARD
VERSION:2.1
FN:John Peter
N:Peter;John
TITLE:Admin
TEL;CELL:+91 431 524 2345
TEL;WORK;VOICE:+91 436 542 8374
EMAIL;WORK;INTERNET:John#ommail.in
URL:www.facebook.com
ADR;WORK:;;423 ofce sales Center;Newark;DE;3243;USA
ORG:xxx Private limited
END:VCARD
Now what I want is, how to retrieve the data in the VCard format specifically, like getting first name, last name, email id, mobile number, etc. A similar question to this is asked before, but it was in objective-c. I don't know how to do this swift 3. Thanks in advance.
Here's a sample code from Playground I used. It's not the best, but You'll get the idea:
import UIKit
import Contacts
var str = "BEGIN:VCARD \n" +
"VERSION:2.1 \n" +
"FN:John Peter \n" +
"N:Peter;John \n" +
"TITLE:Admin \n" +
"TEL;CELL:+91 431 524 2345 \n" +
"TEL;WORK;VOICE:+91 436 542 8374 \n" +
"EMAIL;WORK;INTERNET:John#ommail.in \n" +
"URL:www.facebook.com \n" +
"ADR;WORK:;;423 ofce sales Center;Newark;DE;3243;USA \n" +
"ORG:xxx Private limited \n" +
"END:VCARD"
if let data = str.data(using: .utf8) {
let contacts = try CNContactVCardSerialization.contacts(with: data)
let contact = contacts.first
print("\(String(describing: contact?.familyName))")
}
The output from CNContactVCardSerialization.contacts(with: data) is an array of CNContact (reference).
Here you can check Updated answer for swift 4 of Mateusz Szlosek
var str = "BEGIN:VCARD \n" +
"VERSION:2.1 \n" +
"FN:John Peter \n" +
"N:Peter;John \n" +
"TITLE:Admin \n" +
"TEL;CELL:+91 431 524 2345 \n" +
"TEL;WORK;VOICE:+91 436 542 8374 \n" +
"EMAIL;WORK;INTERNET:John#ommail.in \n" +
"URL:www.facebook.com \n" +
"ADR;WORK:;;423 ofce sales Center;Newark;DE;3243;USA \n" +
"ORG:xxx Private limited \n" +
"END:VCARD"
func fectchContact(){
if let data = str.data(using: .utf8) {
do{
let contacts = try CNContactVCardSerialization.contacts(with: data)
let contact = contacts.first
print("\(String(describing: contact?.familyName))")
}
catch{
// Error Handling
print(error.localizedDescription)
}
}
}

'Tried to save an object with a new, unsaved child.' swift parse

This is my code :
userEmployer.signUpInBackgroundWithBlock { (success, error) -> Void in
if error != nil {
let errorString = error?.userInfo["error"] as! String
} else {
var queryRole = PFRole.query()
queryRole?.whereKey("name", equalTo: "Employer")
queryRole?.getFirstObjectInBackgroundWithBlock({ (roleObject, error) -> Void in
if error == nil{
var roleToAddUser = roleObject as! PFRole
roleToAddUser.users.addObject(PFUser.currentUser()!)
roleToAddUser.saveInBackground()
}// end of it
})// end of query
}//end of else
}//end of signup
It's really weird because I have the same template of code for registering a different role and it works properly. It keeps throwing
'Tried to save an object with a new, unsaved child.'
I don't understand why it's throwing an error.
First throw call stack:
(
0 CoreFoundation 0x0000000106cddf45 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000106755deb objc_exception_throw + 48
2 CoreFoundation 0x0000000106cdde7d +[NSException raise:format:] + 205
3 post 0x0000000104ec93e2 -[PFPointerObjectEncoder encodeParseObject:] + 108
4 post 0x0000000104ec8874 -[PFEncoder encodeObject:] + 113
5 post 0x0000000104e97e3f __129+[PFRESTQueryCommand findCommandParametersWithOrder:conditions:selectedKeys:includedKeys:limit:skip:extraOptions:tracingEnabled:]_block_invoke97 + 1808
6 CoreFoundation 0x0000000106c4acb5 __65-[__NSDictionaryI enumerateKeysAndObjectsWithOptions:usingBlock:]_block_invoke + 85
7 CoreFoundation 0x0000000106c4abbd -[__NSDictionaryI enumerateKeysAndObjectsWithOptions:usingBlock:] + 237
8 post 0x0000000104e9764d +[PFRESTQueryCommand findCommandParametersWithOrder:conditions:selectedKeys:includedKeys:limit:skip:extraOptions:tracingEnabled:] + 911
9 post 0x0000000104e9727c +[PFRESTQueryCommand findCommandParametersForQueryState:] + 296
10 post 0x0000000104e96d2f +[PFRESTQueryCommand findCommandForQueryState:withSessionToken:] + 79
11 post 0x0000000104ea8c89 __78-[PFQueryController findObjectsAsyncForQueryState:withCancellationToken:user:]_block_invoke + 106
12 post 0x0000000104e4dd0e __37+[BFTask taskFromExecutor:withBlock:]_block_invoke + 78
13 post 0x0000000104e4f470 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke_2 + 112
14 libdispatch.dylib 0x0000000108c18e5d _dispatch_call_block_and_release + 12
15 libdispatch.dylib 0x0000000108c3949b _dispatch_client_callout + 8
16 libdispatch.dylib 0x0000000108c21bef _dispatch_root_queue_drain + 1829
17 libdispatch.dylib 0x0000000108c214c5 _dispatch_worker_thread3 + 111
18 libsystem_pthread.dylib 0x0000000108f81a9d _pthread_wqthread + 729
19 libsystem_pthread.dylib 0x0000000108f7f3dd start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException
added info: When I tap the register button it goes to the tableviewcontroller, I tried removing the segue and it registered the user. seems like the error is inside my tableviewconller. this is the code inside.
//creating a pointer
var userPointer = PFUser.objectWithoutDataWithObjectId(PFUser.currentUser()?.objectId)
query.whereKey("postedBy", equalTo: userPointer)
query.orderByDescending("createdAt")
if PFUser.currentUser() != nil {//added1
let objects = query.findObjects()
for object in (objects as? [PFObject])!{
//print(object.objectId)
self.dataSource.append(object)
self.createdByDate.append((object.objectForKey("closingDate") as? NSDate)!)
print(dataSource)
print(createdByDate)
}
let itemArr:PFObject = self.dataSource[indexPath.row] as! PFObject
cell?.companyPostLabel.text = (PFUser.currentUser()?.objectForKey("companyName")!.capitalizedString)! as String
cell?.occupationPostLabel.text = itemArr["occupation"]!.capitalizedString as! String
let companyImage: PFFile?
companyImage = PFUser.currentUser()?.objectForKey("profileImageEmployer") as! PFFile
companyImage?.getDataInBackgroundWithBlock({ (data, error) -> Void in
if error == nil{
cell?.companyLogoImage.image = UIImage(data: data!)
}
})
} else {
print("user not found")
}
let dateArr = createdByDate[indexPath.row]
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy'-'MM'-'dd' : 'hh':'mm'"
var strDate = dateFormatter.stringFromDate(dateArr)
cell?.closingDateLabel .text = strDate
edit 2 : This line is throwing the error
let query = PFQuery(className: "JobPost")
//creating a pointer
var userPointer = PFUser.objectWithoutDataWithObjectId(PFUser.currentUser()?.objectId)
query.whereKey("postedBy", equalTo: userPointer)
let objects = query.findObjects()
return (objects?.count)!
Make sure your currentUser is saved first. You can check with it's objectId.
if ([PFUser currentUser].objectId == nil)
[[PFUser currentUser] saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
// Perform queryRole
}];
else
// Perform queryRole directly

getting total posts from parse using swift2

Every-time I open the app, it returns 6 rows, even if I created a new user with 1 post, it returns 6 rows. plus when I pull to refresh the data remains the same, I have to reopen the app again to see the new data added. this is my code below,
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if PFUser.currentUser()?.objectId == nil{
PFUser.currentUser()?.saveInBackgroundWithBlock({ (success, error) -> Void in
let query = PFQuery(className: "JobPost")
let userPointer = PFUser.objectWithoutDataWithObjectId(PFUser.currentUser()?.objectId)
query.whereKey("postedBy", equalTo: userPointer)
let objects = query.findObjects()
self.dataSourceAnyObject.append(objects!)
})
} else {
let query = PFQuery(className: "JobPost")
let userPointer = PFUser.objectWithoutDataWithObjectId(PFUser.currentUser()?.objectId)
query.whereKey("postedBy", equalTo: userPointer)
let objects = query.findObjects()
self.dataSourceAnyObject.append(objects!)
}
print("Data's in table =\(dataSourceAnyObject.count)")
return dataSourceAnyObject.count
}
Here is the inside cell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "EmpPostTVCellIdentifier"
let cell: EmpPostTVCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as? EmpPostTVCell
let query = PFQuery(className: "JobPost")
//creating a pointer
var userPointer = PFUser.objectWithoutDataWithObjectId(PFUser.currentUser()?.objectId)
query.whereKey("postedBy", equalTo: userPointer)
query.orderByDescending("createdAt")
let objects = query.findObjects()
for object in (objects as? [PFObject])!{
//print(object.objectId)
self.dataSource.append(object)
self.createdByDate.append((object.objectForKey("closingDate") as? NSDate)!)
print(dataSource)
print(createdByDate)
}
if dataSource.isEmpty{
print("no posts")
}else{
let itemArr:PFObject = self.dataSource[indexPath.row] as! PFObject
cell?.companyPostLabel.text = (PFUser.currentUser()?.objectForKey("companyName")!.capitalizedString)! as String
cell?.occupationPostLabel.text = itemArr["occupation"]!.capitalizedString as! String
cell?.countryPostLabel.text = itemArr["country"]!.capitalizedString as String
let companyImage: PFFile?
companyImage = PFUser.currentUser()?.objectForKey("profileImageEmployer") as! PFFile
companyImage?.getDataInBackgroundWithBlock({ (data, error) -> Void in
if error == nil{
cell?.companyLogoImage.image = UIImage(data: data!)
}
})
let dateArr = createdByDate[indexPath.row]
let strDate = Settings.dateFormatter(dateArr)
cell?.closingDateLabel .text = strDate
}//end of dataosource.isEmpty else clause
//Getting Image
// Configure the cell...
return cell!
}
You need to verify how many objects are returned in the query. Is it really 1 as you expected, or 6? Set a breakpoint and find out at this line:
let objects = query.findObjects()
Another code that could cause the bug would be:
self.dataSourceAnyObject.append(objects!)
Remember, the table view datasource method could be called a number of times. If you append to this array, it could erroneously append a number of times.

Populate tableview in swift

I have this result after parsing XML result.
When I do a println() I get the result perfectly like this
{
description = "Suzuki SX4 - BB71521";
deviceID = 359710042040320;
}
{
description = "Chevrolet Tahoe Noir - Demonstration";
deviceID = 359710042067463;
}
{
description = "Isuzu D'Max AA-08612";
deviceID = 359710042091273;
}
{
description = "Toyota 4 Runner";
deviceID = 359710042110768;
}
But when I try to parse the same result in an UITableView with two Cells, the UITableView appears empty.
Please help me to populate only the table ???
Here is my code
import UIKit
class mtTableViewController: UITableViewController, NSXMLParserDelegate {
var info = NSDictionary();
var parser = NSXMLParser()
var posts = NSMutableArray()
var elements = NSMutableDictionary()
var element = NSString()
override func viewDidLoad()
{
super.viewDidLoad()
self.beginParsing()
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func beginParsing()
{
let url = NSURL(string: "http://localhost:8080")
var auth =
"<GTSRequest command=\"dbget\">" +
"<Authorization account=\"" + "easytrucking" + "\" user=\"" + "admin" + "\" password=\"" + "T8095634934ht" + "\"/>" +
"<Record table=\"Device\" partial=\"true\">" +
"<Field name=\"accountID\">" + "easytrucking" + "</Field>" +
"<Field name=\"description\"/>" +
"</Record>" +
"</GTSRequest>";
// "<Authorization account=\"" + txtAccount.text + "\" user=\"" + txtUserName.text + "\" password=\"" + txtPassword.text + "\"/>" +
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let data : NSData = (auth).dataUsingEncoding(NSUTF8StringEncoding)!;
request.HTTPBody = data;
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
/// println(NSString(data: data, encoding: NSUTF8StringEncoding))
let xml = SWXMLHash.parse(data)
let count = xml["GTSResponse"]["Record"].all.count
for var i = 0; i < count; i++
{
if (xml["GTSResponse"]["Record"][i]["Field"][1].element?.attributes["name"] == "deviceID")
{
self.elements.setObject((xml["GTSResponse"]["Record"][i]["Field"][1].element?.text)!, forKey: "deviceID")
}
if (xml["GTSResponse"]["Record"][i]["Field"][3].element?.attributes["name"] == "description")
{
self.elements.setObject((xml["GTSResponse"]["Record"][i]["Field"][3].element?.text)!, forKey: "description")
}
self.posts.addObject(self.elements)
// here i print the result
println(self.elements)
}
}
}
//Tableview Methods
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return posts.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell : UITableViewCell! = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
if(cell == nil) {
cell = NSBundle.mainBundle().loadNibNamed("Cell", owner: self, options: nil)[0] as UITableViewCell;
}
cell.textLabel?.text = posts.objectAtIndex(indexPath.row).valueForKey("deviceID") as NSString
cell.detailTextLabel?.text = posts.objectAtIndex(indexPath.row).valueForKey("description") as NSString
return cell as UITableViewCell
}
}
Please help !!!
There are two problems. First, NSURLConnection.sendAsynchronousRequest()
– as the name indicates – works asynchronously: It initiates a network
request and then returns. The completion handler is called later, when
the data is has arrived. Then you have to reload the table view with
tableView.reloadData()
after populating the data source array with the new data.
Second, in
for var i = 0; i < count; i++
{
self.elements.setObject(..., forKey: ...)
self.elements.setObject(..., forKey: ...)
// ...
self.posts.addObject(self.elements)
}
you are modifying the same dictionary again and again. NSMutableArray
and NSMutableDictionary are reference types, therefore you end up
with an array containing count pointers to the same dictionary
(containing the data from the last loop execution).
Instead of a having a single dictionary as property
var elements = NSMutableDictionary()
this should be a local variable in your loop:
for var i = 0; i < count; i++
{
var elements = NSMutableDictionary()
self.elements.setObject(..., forKey: ...)
self.elements.setObject(..., forKey: ...)
// ...
self.posts.addObject(elements)
}
You might also consider to use Swift arrays and dictionaries instead.
These are value types which makes this kind of error much less
likely.

PFQueryTableView Controller not loading custom Cells

Im working on an app and I would like it to populate the cells based on users who are within a set distance from the currentuser. For some reason the customcells are not being populated with the correct objects. The labels and images that are supposed to be retrieved are blank. All i get is a blank cell. I made sure i gave the cell identifier the correct name, and i also made sure to link the tableviewcontroller and the tablecellview to their respective classes,but still no luck.
first i created initializers:
class TableViewController: PFQueryTableViewController, CLLocationManagerDelegate {
let locationManager = CLLocationManager()
var currLocation: CLLocationCoordinate2D?
override init!(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.parseClassName = "User"
self.textKey = "FBName"
// self.imageKey = "pictureURL"
self.pullToRefreshEnabled = true
self.objectsPerPage = 10
self.paginationEnabled = true
}
Then in viewDidLoad i enabled location services:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 200
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
loadData()
println("location services enabled bruh")
}
}
Next i overrode the queryfortable function:
override func queryForTable() -> PFQuery! {
let query = PFQuery(className: "User")
if let queryLoc = currLocation {
query.whereKey("location", nearGeoPoint: PFGeoPoint(latitude: queryLoc.latitude, longitude: queryLoc.longitude), withinMiles: 50)
query.limit = 40
query.orderByAscending("createdAt")
println("\(queryLoc.latitude)")
return query
} else {
query.whereKey("location", nearGeoPoint: PFGeoPoint(latitude: 37.411822, longitude: -121.941125), withinMiles: 50)
query.limit = 40
query.orderByAscending("createdAt")
println("else statement")
return query
}
}
then the objectAtIndexPath function
override func objectAtIndexPath(indexPath: NSIndexPath!) -> PFObject! {
var obj : PFObject? = nil
if indexPath.row < self.objects.count {
obj = self.objects[indexPath.row] as? PFObject
}
return obj
}
and lastly I returned the cell, but for some reason it does not work:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!, object: PFObject?) -> PFTableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell", forIndexPath: indexPath) as TableViewCell
cell.userName?.text = object?.valueForKey("FBName") as? String
let userProfilePhotoURLString = object?.valueForKey("pictureURL") as? String
var pictureURL: NSURL = NSURL(string: userProfilePhotoURLString!)!
var urlRequest: NSURLRequest = NSURLRequest(URL: pictureURL)
NSURLConnection.sendAsynchronousRequest(urlRequest, queue: NSOperationQueue.mainQueue()) { (NSURLResponse response, NSData data,NSError error) -> Void in
if error == nil && data != nil {
cell.userImage?.image = UIImage(data: data)
}
}
cell.ratingsView?.show(rating: 4.0, text: nil)
return cell
}
ps, i have the number of sections set to 1, just didnt think that method would be useful to show here.
okay I found the issue! The issue was that I was trying to use PFQuery in order to retrieve a list of PFUsers. I found out that cannot be done using PFQuery infact PFUser has it's own query method for retrieving information from its users.
all i had to do was replace this line:
let query = PFQuery(className: "User")
with this:
let query = PFUser.query()

Resources