Updating object in Parse iOS - ios

I am having trouble translating Parse documentation into new Swift requirements. I want to update an object but I keep getting back an error that I can't assign a value of type Bool to type AnyObject? I know the column for "viewed" is Bool. Here is my code.
var query = PFQuery(className:"Post")
query.getObjectInBackgroundWithId(self.threadImageIds[objectIDkey]) {
(object, error) -> Void in
if error != nil {
println(error)
} else {
object["viewed"] = true // this is where error is occuring
object!.saveInBackground()
}
}
Thanks in advance.

After a lot of searching and trying to unwrap optionals the way Swift wants me to, the following worked
query.getObjectInBackgroundWithId(self.threadImageIds[objectIDkey]) {
(object, error) -> Void in
if error != nil {
println(error)
} else {
if let object = object {
object["viewed"] = true as Bool
}
object!.saveInBackground()
}
}

You can't store a BOOL there, you need to use a NSNumber of a BOOL. Try true as NSNumber

It is not working because you're trying to apply the subscript to the optional and not to the object, so try unwrapping
object!["viewed"] = true

Related

Updating object in Parse iOS, [Error]: Object not found

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
// Set up the Parse SDK
let configuration = ParseClientConfiguration {
$0.applicationId = "WhatsTheHW"
$0.server = "https://whatsthehw-parse-alan.herokuapp.com/parse"
}
Parse.initializeWithConfiguration(configuration)
let query = PFQuery(className: "Course")
query.findObjectsInBackgroundWithBlock {(result: [PFObject]?, error: NSError?) -> Void in
for object in result! {
// existing objectIds: 1Ja2Hx77zA, 34AF1vKO6f, 5FWlsswxw0
if object.objectId == "34AF1vKO6f" {
object["studentRelation"] = ["hi", "ih"]
object.saveInBackgroundWithBlock{(success, error) in
if success == true {
print("\(object) saved to parse")
} else {
print("save failed: \(error)")
}
}
}
}
}
return true
}
This is the minimum I can reduce this task to (this code is at AppDelegate).
It all worked fine when I tried using REST api and api console in parse dashboard but it doesn't work with iOS sdk.
The error I'm getting from the print statement is
Error Domain=Parse Code=101 "Object not found." UserInfo={code=101, temporary=0, error=Object not found., NSLocalizedDescription=Object not found.}
It works if I'm simply adding a new object like this :
let object = PFObject(className: "Course")
object["name"] = "German"
object["studentRelation"] = ["a", "b"]
object.saveInBackgroundWithBlock{(success, error) in
if success == true {
print("save completed")
print("\(object) saved to parse")
} else {
print("save failed: \(error)")
}
}
I'm really lost and I don't know why this is happening.
Thanks in advance.
This issue might relate to the access rights (ACL) of the object that you're trying to save. [Error]: Object not found is printed when a user that doesn't have write access to an object tries to save it, the error message of the Parse SDK is really misleading here!
Make sure the parse user who is trying to save the object has the proper writes to actually write on that object in your parse DB.
An easy fix will be to set the default ACL inside your app to public read + write:
let acl = PFACL()
acl.publicReadAccess = true
acl.publicWriteAccess = true
PFACL.setDefaultACL(acl, withAccessForCurrentUser: true)
Be careful with this approach though, usually you want to set access rights according to the actual role of the user. So a better alternative would be to only set the ACL on the PFObject when you're creating it and only give write access to the users you know should be able to alter the object.
can you please first find your object, save into another object and run the saveInBackground outside of the loop.
Your code should look like the following:
var objectToSave : PFObject?
let query = PFQuery(className: "Course")
query.findObjectsInBackgroundWithBlock {(result: [PFObject]?, error: NSError?) -> Void in
for object in result! {
if object.objectId == "jMIxdSXNRH" {
objectToSave = object
}
}
if objectToSave != nil {
objectToSave!["studentRelation"] = ["hi", "ih"]
objectToSave!.saveInBackgroundWithBlock{(success, error) in
if success == true {
print("\(objectToSave) saved to parse")
} else {
print("save failed: \(error)")
}
}
}
}
I am using my objectId's and not your so please change them to yours :)

how to convert [NSManagedObject] to nsmutable array (Swift)

i am using coredata in my app. i am storing 50 city in my core data. now i want to use search bar. which was working well with array. and i am using filtering for that. here is my code for that
arrcity.enumerateObjectsUsingBlock({ (obj, _, _) -> Void in
if let city : SelectCityModel = obj as? SelectCityModel
{
if city.city.lowercaseString.rangeOfString(self.searchtext.lowercaseString) != nil
{
self.searchcity?.addObject(city)
}
}
})
now i want to do same process but i have [nsmanagedobject] people. so how can i do this. it will be ease if is there any way to convert [NsmanagedObject] to nsmutablearry.
here is my code
if (people.count > 0)
{
people.enumerateObjectsUsingBlock({ (obj, _, _) -> Void in
if let city : SelectCityModel = obj as? SelectCityModel
{
if city.city.lowercaseString.rangeOfString(self.searchtext.lowercaseString) != nil
{
self.searchcity?.addObject(city)
}
}
})
}
but here var people = NSManagedObject so how can i convert it?
NSMutableArray is not related to a Swift Array.
But you could use the Swift Array with a native enumerator, for example
people.forEach { [unowned self] (object) -> () in
if object is SelectCityModel
{
if object.city.lowercaseString.rangeOfString(self.searchtext.lowercaseString) != nil
{
self.searchcity?.addObject(city)
}
}
}
If people is always [SelectCityModel] cast it to that type in the fetch line and omit the type check in the forEach closure. The check if people > 0 is not needed either.
A more convenient way is to use the filter and map functions.
self.searchcity = people.filter({$0.city.lowercaseString.rangeOfString(self.searchtext.lowercaseString) != nil}).map{ $0.city }

Swift can't update Parse object

I have a problem and I could really use some help..
I have the method below and everything works fine, until line 907.. When it comes for the object3.saveInBackgroundWithBlock, it does nothing.. Not even errors! It never saves the object and it never goes inside the block..
Any idea why?
func addUserToThoseIFollow(sender: UIButton) {
//self.navigationItem.rightBarButtonItem?.enabled = false
sender.enabled = false
let userQuery = PFQuery(className: "_User")
let userQuery2 = PFQuery(className: "_User")
userQuery.getObjectInBackgroundWithId(PFUser.currentUser().objectId) { (object: PFObject!, error: NSError!) -> Void in
if error == nil {
// If I already follow some users, make
// an array with them, add the user I
// want to follow and save. Else,
// just save an array, with that one user.
if object["following"] != nil {
var thoseIFollow = object["following"] as! [String]
thoseIFollow.append(self.userID!)
object["following"] = thoseIFollow
}
else {
var myUsers = [String]()
myUsers.append(self.userID!)
object["following"] = myUsers
}
object.saveInBackgroundWithBlock({ (ok: Bool, error2: NSError!) -> Void in
if error2 == nil {
self.followButton.setTitle("Unfollow", forState: .Normal)
self.followButton.backgroundColor = UIColor(red: 1, green: 0, blue: 0, alpha: 0.7)
sender.enabled = true
self.doIFollow = true
}
})
}
}
// Add me to his followers
userQuery2.getObjectInBackgroundWithId(self.userID) { (object3: PFObject!, error3: NSError!) -> Void in
if error3 == nil {
// If the user I just followed, has already followers, make
// an array with them and add the current user to
// them. Else, just save an array, with the current user.
if object3["followers"] != nil {
var hisFollowers = object3["followers"] as! [String]
hisFollowers.append(PFUser.currentUser().objectId)
object3["followers"] = hisFollowers
/* Line 907 */ object3.saveInBackgroundWithBlock({ (ok7: Bool, error7: NSError?) -> Void in // Line 907
if error7 == nil {
print("ok")
}
else {
print(error7)
}
})
}
else {
var hisFollowers = [String]()
hisFollowers.append(PFUser.currentUser().objectId)
object3["followers"] = hisFollowers
object3.saveInBackgroundWithBlock( { (ok5: Bool, error7: NSError!) -> Void in
print("otinanai")
if error7 != nil {
print(error7.localizedDescription)
}
})
}
}
}
}
Attempt #1
What PFUser.currentUser().objectId return ? If it returns nil so it doesn't work.
Attempt #2
Available Parse Types
So far we've used values with type NSString, NSNumber, and PFObject. Parse also supports NSDate, and NSNull.
You can nest NSDictionary and NSArray objects to store more structured data within a single PFObject.
Try to use var hisFollowers = [NSString]() instead of var hisFollowers = [String]()
self.userID
Where exactly is this coming from?
Did your check, whether it is an optional?
Comment out the first query and see if it works.
Each Parse object can only have one background thread running for it at a time. Say you save an object, then immediately in the next line (not inside of its call back), edit it and then save it again. The second save will not be called, since the first save is still running. You don't even get an error. You get zero notification whatsoever that this call didn't happen.
My guess is that you have objects being saved inside both the first query and the second query, and because of that, the second query's save is being skipped.
The solution would be to stick the second query inside of the first's callback.
I think that there's a PromiseKit library you can download that adds javascript functionality in iOS, making it more similar to how you'd chain these calls in cloud code, but I haven't used it.

Check if PFObject is nil

I want to check if a PFObject is nil
I retrieve the object
var userLibrary: PFObject?
func getUserLibrary(user: PFUser) {
self.libraryQuery = PFQuery(className: "Library")
self.libraryQuery?.whereKey("owner", equalTo: user)
self.libraryQuery?.findObjectsInBackgroundWithBlock({ (objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
if objects!.count > 0 {
self.userLibrary = objects![0]
} else {
print(self.userLibrary)
}
}
})
}
The last line with the print statement prints out nil.
However when I check :
if userLibrary != nil {
}
Xcode tells me
Binary operator '!=' cannot be applied to operands of type 'PFObject' and 'NilLiteralConvertible'
How do I fix this ?
I'm not 100% sure that this will work, but did you try.
if let lib = userLibrary {
//do whatever
}
Let me know.
Also, if you are just using the first object of your query. It would better to use getFirstObjectInBackground

Cloud Kit's performQuery in Swift 2.0

Hi.
I'm trying to make Cloud Kit based app. For data fetch I'm using this
privateDatabase.performQuery(query, inZoneWithID: nil) {
results, error in
if error != nil {
print(error)
} else {
print(results)
for item in results {
self.workoutData.append(item as! CKRecord)
}
}
}
but XCode says
'[CKRecord]?' does not have a member named 'Generator'
Can you help me please?
You need to unwrap the CKRecord array like so:
if let res = results {
for item in res! {
//Do things with item
}
}

Resources