Accessing .recordFields from CKQueryNotification Swift 2 - swift

I get the following error on didReceiveRemoteNotifications if I try to simply print this property, like:
let cloudKitNotification = CKNotification(fromRemoteNotificationDictionary: userInfo as! [String : NSObject])
if cloudKitNotification.notificationType == .Query {
let queryNotification = cloudKitNotification as! CKQueryNotification
print(queryNotification.recordFields)
Could not cast value of type '__NSCFDictionary' (0x273119c) to 'CKRecordValue' (0x2763090).
If I print the whole queryNotification, I can see the recordFields inside of it. I've spent the whole day trying to understand that. Any clues?
Xcode 7.3.1

Related

Cannot call value of non-function type 'Any'

i want to fix this problem Cannot call value of non-function type 'Any'
this is my code
databaseRef.child("ServiceA").queryOrderedByKey().observe(.childAdded, with: {
DataSnapshot in
let title = DataSnapshot.value!("title") as! String
self.posts.insert(PostStruct.init(title: title), at: 0)
})
Is there a way to fix it?
Thanks
DataSnapshot.value is Any and according to the documentation you could cast it in different types.
Data types returned: + NSDictionary + NSArray + NSNumber (also includes booleans) + NSString
If I understood your snipped well, in you case, you need to cast "DataSnapshot" into a dictionary in order to access with a subscript.
You can try this:
databaseRef.child("ServiceA").queryOrderedByKey().observe(.childAdded, with: {
DataSnapshot in
let title = (snapshot.value as? [String: Any])?["title"] as? String
self.posts.insert(PostStruct.init(title: title), at: 0)
})
Please also note that, in order to prevent crashes, I removed the force-wrap so "title" would be an optional String.

Swift Array to Set : Showing Recent Messages Command failed due to signal: Segmentation fault: 11

I am using firebase to retrieve a list of data then convert it to an NSDictonary array. I want to parse the data by a property e.g name
func getAllMyModels() {
if let e = email {
_ = ref.child("childName").queryOrdered(byChild: "email").queryEqual(toValue: e).observe(.value) { snapshot in
var dictionary = [NSDictionary]()
let children = snapshot.children
while let rest = children.nextObject() as? DataSnapshot, let value = rest.value {
dictionary.append(NSDictionary(dictionary: value as! [String: Any]))
}
let names = dictionary.flatMap {$0["name"]} // names print correct values
let set = Set(names)
print(set)
}
}
}
This code can't be complied the error is:
Showing Recent Messages
Command failed due to signal: Segmentation fault: 11
If i removed this line:
let set = Set(Array(names))
all works fine.
I also tested by replace it by this block
let ar = ["name1","name2"].flatMap { return $0 }
Set(ar)
No errors.
Not sure why? Who can tell, thanks!
EDIT: Even though the element in the array is String type but the names array is [Any], so the solution is
let names = dictionary.flatMap {$0["name"]} as! [String]
I think this errors occurs because the Array you generate from the dictionary with flatMap is an Array of Any and not a String Array, try to cast to a String like this:
...
let names = dictionary.flatMap {$0["name"] as? String}
let set = Set(Array(names))
...
Hope this help you
Cast names to [String]:
let names = dictionary.flatMap {$0["name"]} as! [String]

Unable to convert anyObject to String

I am trying to run the following code, but am unable to convert the rest.value without the preceeding "Optional". The following is the code I get when attempting to solve the issue:
//for Withdrawl children
transRef.child("Withdraw").observeSingleEventOfType(.Value, withBlock: { (snapshot) in
//creates enumerator of the snapshot children for
let enumerator = snapshot.children
while let rest = enumerator.nextObject() as? FIRDataSnapshot {
let curString = (rest.value) as! String
self.anArray.append(curString)
//printing the rest.value to make sure there are children to iterate through
print(rest.value)
}
self.tableView.reloadData() //<<<<<<<<<<<< RELOAD TABLEVIEW
})
this is the error I am receiving: Could not cast value of type '__NSCFNumber' (0x10d068368) to 'NSString'
According to the Firebase documentation the value property: "Returns the contents of this data snapshot as native types. Data types returned: + NSDictionary + NSArray + NSNumber (also includes booleans) + NSString".
The var returns an Any? in order to handle this versatility.
In this case it looks like it is returning an NSNumber, so the String cast fails. I'm not sure exactly the context of the value in this scenario, but if you are sure that it is going to return a number every time you could cast it to a numerical type (Swift/Objective-C bridging allows NSNumber to be casted to any of the primitive number types in Swift), and then pass it into a String initializer to get a String out of it. e.g.:
let curNumber = rest.value as! Double
let curString = String(curNumber)
If you aren't sure what type will be returned, but are expecting to put it into an Array of Strings then you should probably check before you cast e.g.:
if let curNumber = rest.value as? Double {
let curString = String(curNumber)
self.anArray.append(curString)
}
Instead of (rest.value) as! String, say [Swift 2] String(rest.value) or [Swift 3] String(describing:rest.value). [If rest.value is an Optional, then say rest.value! in those formulations.]

<= Operand asking for expected type in Swift?

I'm trying to look for items equal or less than zero in my query like so.....
for zeroItems in snapshot.value as! NSDictionary where zeroItems.value["Value"] as! Int <= 0
I'm getting an Expected type error. Please explain and show me how to correct.
You may want to consider applying a filter to simplify the logic to only include elements less than zero. I've created a working example in the IBM Swift Sandbox.
import Foundation
// Construct the data structure with demo data
struct Snapshot {
let value: NSDictionary
}
let dict: NSDictionary = [ "a" : -1, "b" : 0, "c" : 1]
let snapshot = Snapshot(value: dict)
//Apply a filter
let zeroItems = snapshot.value.filter{Int($0.1 as! NSNumber) <= 0}
//View the result
print(zeroItems)
Almost certainly you've overused Any if you have to use this many as! casts in a single line. Create a custom struct for this type and convert the data to that. If you're passing around NSDictionary and using as! very much, you're fighting the system.
That said, to make this work you probably just need more parentheses. Something like:
for zeroItems in (snapshot.value as! NSDictionary) where (zeroItems.value["Value"] as! Int) <= 0
But this is horrible Swift, so avoid this if possible.
You interpreting snapshot.value as Dictionary, so zeroItems is a tuple of key and value.
As I understand you having array of dictionaries, and you want to filter them by "Value" key, right?
If so then you may use following code:
// dictionary with Value key, and Int value
let dict: [String: Any] = ["Value":-1]
// array of dictionaries
let value: [[String: Any]] = [dict, <**add here as many as you want**>]
// get only array of integeres
let onlyIntegers = value.flatMap { $0["Value"] as? Int }.filter {$0 <= 0 }
print(onlyIntegers)
// get array of dictionaries which passes <=0 check
let onlyLessOrEqualTo0 = value.filter { dict in
if let value = dict["Value"] as? Int {
return value <= 0
}
return false
}
print(onlyLessOrEqualTo0)
First of all, adding some parentheses will help in seeing where the problem is:
for zeroItems in myDict as! NSDictionary where (zeroItems.value["Value"] as! Int) <= 0
Now, we get "Type 'Any' has no subscript members". So the problem is that you haven't told Swift what the type is of zeroItems's value, which I think is a dictionary of , judging from your code:
This compiles for me:
for zeroItems in myDict as! Dictionary<String, Dictionary<String, Int>> where zeroItems.value["Value"]! <= 0
However, this is not pretty. You could probably get more readable code using filter as was suggested in another answer.

Error when using NSUserDefaults

I've been trying for weeks now to save some values in one view controller then access them in another using the NSUserDefaults method. I am using this code:
(to save):
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("Coding Explorer", forKey: "userNameKey")
the last line produces an "expected declaration" error
(to get values):
let defaults = NSUserDefaults.standardUserDefaults()
if let name = defaults.stringForKey("userNameKey")
{
println(name)
}
The first of these lines produces a "incorrect redeclarion of 'defaults'"
second line produces "expected declaration"
third line produces "Consecutive declarions on a line must be seperated by a ;" and "variables used within its own initial value"
Please help me fix this I've tried different lots of code to use NSUserDefaults, and I've tried using the code on separate and the same view controllers.
You may try to use this way..
to save first define a string called for example "firstName":
var firstName : String = "Im Swift"
in viewDidLoad in the first ViewController :
if (NSUserDefaults.standardUserDefaults().stringForKey("firstName") == nil){
NSUserDefaults.standardUserDefaults().setObject(firstName, forKey: "firstName")
}
To retrieve value :
in the viewDidLoad of second ViewController :
if (NSUserDefaults.standardUserDefaults().stringForKey("firstName") != nil){
var x = NSUserDefaults.standardUserDefaults().objectForKey("firstName") as! String
println("\(x)");
}