Optional Types With Parse and Swift - swift

if var findPublisher:PFQuery = PFUser.query(){
findPublisher.whereKey("objectId", equalTo:quote.objectForKey("publisher").objectId)//error here
}
I am getting an error Value of any optional type 'Any Object'? not unwrapped. I don't know what i have done incorrectly. I am a beginner so please bear with me:)

This is really a place where you would give each quote a pointer to a user object, and then you could just get the publisher of the quote without an extra query. But if you want to do it this way, you would do:
let query = PFUser.query()!
query.whereKey("objectId", equalTo: (quote["publisher"] as! String)) // You can unwrap it as long as you are sure that quote is not nil, and the publisher is set.
query.getFirstObjectInBackgroundWithBlock({ (user: PFObject?, error: NSError?) in
// check for errors and use the object
})
This way of doing it also creates Parse security issues, as anyone with your app's ID and key can get a full user list.

let findPublisher = PFUser.query()!
findPublisher.whereKey("objectId", equalTo: (quote["publisher"] as! String))
findPublisher.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]?, error:NSError?)->Void in
if error == nil{
let user:PFUser = (objects as NSArray).lastObject as! PFUser//error here
cell.publisherLabel.text = user.username
}
}
I end up getting an error that says that AnyObject is not convertible to NSArray?

Related

Swift error while downcasting 'Any'

The following code is almost exact replica from Apple Documentation and compiles without errors:
guard let firstItem = (rawItems! as? Array<Dictionary<String, Any>>)?.first else {
throw AnError()
}
let identityRef = firstItem[kSecImportItemIdentity as String]
as! SecIdentity? // !!!
guard let identity = identityRef else {
throw AnError()
}
The line marked with !!! contains forced downcast, while replacing as! with as quite obviously results in a compilation error 'Any?' is not convertible to 'SecIdentity?'... Indeed SecIdentity is a class while Any may not even be a class.
What I really cannot explain is the following. If I try to make the code safer, by using this
guard let idenity = firstItem[kSecImportItemIdentity as String] as? SecIdentity
else {
throw AnError()
}
or this
guard let idenityRef = firstItem[kSecImportItemIdentity as String] as? SecIdentity?
else {
throw AnError()
}
I get a compilation error: Conditional downcast to CoreFoundation type 'SecIdentity' will always succeed
SecIdentity is “an abstract Core Foundation-type object representing an identity, ” and the type of Core Foundation types can be
checked with CFGetTypeID(). So you can check the type ID first. If it matches the type ID of an
SecIdentity then the forced cast is safe:
guard let cfIdentity = firstItem[kSecImportItemIdentity as String] as CFTypeRef?,
CFGetTypeID(cfIdentity) == SecIdentityGetTypeID() else {
throw AnError()
}
let identity = cfIdentity as! SecIdentity
See also the bug report SR-7015 The CoreFoundation conditional downcast diagnostic is not as helpful as it should be:
The diagnostic should be updated with a message that informs the developer to compare CFTypeIds (with a fixit if possible).
CoreFoundation types behave a bit differently from Foundation types.
Don't conditional downcast the identity. If the optional binding succeeds you can force unwrap the identity
guard let idenity = firstItem[kSecImportItemIdentity as String] else { throw AnError() }
var privateKey : SecKey?
let status = SecIdentityCopyPrivateKey(identity as! SecIdentity, &privateKey)
Side note :
Please never write as? SecIdentity?.
Either it's conditional downcast as? SecIdentity or bridge cast an optional as SecIdentity?

Swift 4 - Catch Error if Value not in Plist

I have this code
let path = self.userDesktopDirectory + "/Library/Preferences/.GlobalPreferences.plist"
let dictRoot = NSDictionary(contentsOfFile: path)
if let dict = dictRoot{
try print(dict["AppleLocale"] as! String)
}
If the Value "AppleLocale" didnt exists the script crashes. What I must add to "catch" the Error and avoid the crash?
If the Value "AppleLocale" didnt exists the script crashes. What I
must add to "catch" the Error and avoid the crash?
depends on what's the reason for causing the crash. Mentioning that "If the Value AppleLocale didnt exists" means the the reason for the crash would be the force casting:
dict["AppleLocale"] as! String
probably, it has nothing to do with the try, it would be:
Unexpectedly found nil while unwrapping an Optional value
Means that at some point dict["AppleLocale"] could be nil or even if it contains a value as not a string it will crash (optional). You have to make sure that dict["AppleLocale"] is a valid (not nil) string, there are more than just one approach to follow for doing it, for instance you could do optional binding, like this:
let path = self.userDesktopDirectory + "/Library/Preferences/.GlobalPreferences.plist"
let dictRoot = NSDictionary(contentsOfFile: path)
if let dict = dictRoot{
if let appleLocale = dict["AppleLocale"] as? String {
print(appleLocale)
} else {
// `dict["AppleLocale"]` is nil OR contains not string value
}
}
Actually, I would assume that you don't have to deal with try for such a case.

Swift - Parse Query whereKey contains

I have a parse object that i have saved to the LDS and i want to search for it via 1 key and an entry under another key.
Key: This is fine.
checkQuery.whereKeyExists("File-rZVgZNpNuB")
Key that contains: This does not work.
checkQuery.whereKey("seachKey", contains: "myItem0000000000")
The console is printing:
-[__NSArrayM length]: unrecognized selector sent to instance 0x7c09bbb0
I'm guessing because the mySearchString is an object within the "searchKey" field which returns an NSMutable Array. its easy enough to get the data out of the array once i have the object but i need to search for this string in the "searchKey" field to find the object. For various reasons i can not just save the object with a key of "myItem0000000000". perhaps i could add it as a third key when i save the object but that seems a bit messy.
It is there, if i look at the object through SQL Lite i can see it.
{"className":"downloadedAudio","__complete":true,"__operations":[{"ACL":{"*":{"read":true},"rZVgZNpNuB":{"write":true,"read":true}},"File-rZVgZNpNuB":{"__op":"Add","objects":[{"url":"https:\/\/parse-server-nextbreath-s3-bucket.s3.amazonaws.com\/b5d2110dce0b50dc3a1c620731fad66e_The%20Name%20of%20the%20Wind%2024-92.mp3","name":"b5d2110dce0b50dc3a1c620731fad66e_The Name of the Wind 24-92.mp3","__type":"File"}]},"__uuid":"77AE38AF-1ADB-4795-9BB0-5A5AB7205E28","__updatedAt":{"iso":"2017-03-03T21:28:19.637Z","__type":"Date"},"searchKey":{"__op":"Add","objects":["myItem0000000000"]}}],"isDeletingEventually":0}
---- EDIT ----
searching:
let searchKey = "File-\(PFUser.current()!.objectId!)"
let checkQuery = PFQuery(className: "downloadedAudio")
checkQuery.whereKeyExists(searchKey)
//checkQuery.whereKeyExists(item.name)
//checkQuery.whereKey("seachKey", contains: item.name)
checkQuery.fromLocalDatastore()
checkQuery.getFirstObjectInBackground(block: { (object, error) in
if object != nil {
// object?.unpinInBackground()
object?.unpinInBackground(block: { (success, error) in
if success {
saving:
let query = PFQuery(className: "Part")
query.whereKey("objectId", equalTo: selectedObjectId)
query.getFirstObjectInBackground { (object, error) in
if error != nil || object == nil {
// ----
} else {
let searchKey = "File-\(PFUser.current()!.objectId!)"
downloadedAudio.add(object?.object(forKey: "partAudio") as! PFFile, forKey: file)
downloadedAudio.add(object?.object(forKey: "partName") as! String, forKey: searchKey)
let downloadedFile = object?.object(forKey: "partAudio") as! PFFile
downloadedFile.getDataInBackground({ (data, error) in
I do believe you are getting that error because "File-rZVgZNpNuB" is an invalid key. Remember that keys can only start with a lowercase letter.

Array of Parse Pointers (Swift) - is This Possible

I am working on an app where the user is connected (in) multiple school classes. Since a student will be in more than one class, am I able to set an array of pointers to an individual user or is that not possible (maybe a relation is better)?
Here is my code:
let classPointerQuery = PFQuery(className: "Classes")
classPointerQuery.whereKey("class_name", equalTo: self.classNameTextField.text!)
let classQuery = PFQuery.orQueryWithSubqueries([classPointerQuery])
classQuery.findObjectsInBackgroundWithBlock({ (results: [PFObject]?, error: NSError?) -> Void in
if let objects = results {
for object in objects {
let userInfo = PFUser.currentUser()!
userInfo["my_classes"] = object
userInfo.saveInBackgroundWithBlock({ (success: Bool, error: NSError?) -> Void in
if error != nil {
spinningActivity.hideAnimated(true)
self.displayAlert("Error", message: error!.localizedDescription)
} else if success {
spinningActivity.hideAnimated(true)
self.dismissViewControllerAnimated(true, completion: nil)
} else {
spinningActivity.hideAnimated(true)
self.displayAlert("Something Went Wrong", message: "Please try again")
}
})
}
}
})
* Note: I also tried changing - userInfo["my_classes"] = object - to - userInfo["my_classes"] = [object] - and got an error, "invalid type for key my_classes, expected *Classes, but got array (Code: 111, Version: 1.12.0)"
What I am doing here is querying for the object of the class that I want - lets say the user wants to add the class "Physics" - the query queries for the "class_name" in the Parse class "Classes" and spits out the object. This object is then set the current user's "my_classes" -> a pointer object. I there a way, when the user wants to add "Calculus" that the pointer object in Parse will have 2 pointers instead of replacing the current pointer?
Thanks in advance for the help!
you cant store Pointers in array, you can store objectID in the array as string and do the query like that.... the general rule is that u use Pointers for 1:many relationships in database and Relations in many:many...
Update 1 - Saving objectID to Array in Parse
PFUser.currentUser()!.addObject(somePFObject.objectID!, forKey: "my_classes")
for queries you will than use containedIn
querySetup.whereKey("class", containedIn: array)

Extra argument in Call for Parse in Swift

All I am trying to get multiple objects out of a parse database.
Here is some of my code :
So this does the query :
var MainPicture = PFQuery(className: "Staff")
MainPicture.whereKey("Position", equalTo: "Sales Manager")
MainPicture.findObjectsInBackgroundWithBlock ({(objects:[AnyObject]!, error: NSError!) in
if(error == nil){
self.getMainImageData(objects as [PFObject])
}
else{
println("Error in retrieving \(error)")
}
Then I want to get a few rows out of the query :
func getMainImageData(objects: [PFObject]) {
for object in objects {
let MainPic = object["StaffPic"] as PFFile
let MainData = object["FirstName","SecondName","Position"] as PFFile
MainPic let works, but when I try and do multiple ones like MainData , I get an error : "Extra argument in call" .. I thought this would have worked.
I suspect you cannot subscript PFObject with multiple items. It is like calling
dictionary["key1", "key2"]
That will also result in too many arguments.
It is confusing that your variables are Capitalized. They look like class names.