Firebase Swift 3.0 setValuesForKeysWithDictionary - swift

Here is the code:
func observeMessages() {
let ref = FIRDatabase.database().reference().child("messages")
ref.observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let message = Message()
message.setValuesForKeys(dictionary)
self.messages.append(message)
//this will crash because of background thread, so lets call this on dispatch_async main thread
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
}, withCancel: nil)
}
When run, it crashes like this:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key name.'
Please kindly help me fix this.

The problem is that there is a mismatch between your Message model class and what you are trying to put inside of your instance of it through the setValuesForKeys method. Your dictionary does not line up with the Message class.
This is what the error message tells you: your app tried to set a value for a key from your snapshot.value that does not exist in your Message class.
Check that there is exactly the same number of properties with the same name in your Message class as in your snapshot.value.
To avoid mismatches, you could define your Message class as such:
class Message: NSObject {
var fromId: String?
var text: String?
var timestamp: NSNumber?
var toId: String?
var imageUrl: String?
var imageWidth: NSNumber?
var imageHeight: NSNumber?
init(dictionary: [String: AnyObject]) {
super.init()
fromId = dictionary["fromId"] as? String
text = dictionary["text"] as? String
timestamp = dictionary["timestamp"] as? NSNumber
toId = dictionary["toId"] as? String
imageUrl = dictionary["imageUrl"] as? String
imageWidth = dictionary["imageWidth"] as? NSNumber
imageHeight = dictionary["imageHeight"] as? NSNumber
}
}

Related

how to add firebase element to dictionary

I have this empty dictionary
let orderArray = ["name":"","quntity":"","price":""]
and when i download the data from Firebase, i want to get some elements and put them in the dictionary to read it later
Here's my Firebase method:
self.databaseRef.child("Users").child((Auth.auth().currentUser?.uid)!).child("cart").child(self.orderFromKitchen).observe(DataEventType.value, with: { (snapshot) in
//if the reference have some values
if snapshot.childrenCount > 0 {
//clearing the list
self.ordersList.removeAll()
//iterating through all the values
for info in snapshot.children.allObjects as! [DataSnapshot] {
//getting values
//let key = self.kitchensRef.childByAutoId().key
let infoObject = info.value as? [String: AnyObject]
let name = infoObject?["name"]
let Id = infoObject?["ID"]
let img = infoObject?["img"]
let price = infoObject?["price"]
let quantity = infoObject?["quntity"]
self.nameArr.append((name as! String?)!)
self.quaArr.append((quantity as! String?)!)
let info = ordersModel(id: Id as! String?, name: name as! String?, img: img as! String?, price: price as? Int,quantity:quantity as! String?)
//here i want to add name and price to the dictionary
self.orderArray.insert(contentsOf: "\(infoObject?["name"]!)", at: 0)
self.orderArray.insert(contentsOf: "\(infoObject?["price"]!)", at: 2)
self.ordersList.append(info)
}
//reloading the tableview
self.tableView.reloadData()
self.loadingView.isHidden = true
}
Thank you guys i fixed it by this greate extention
extension Dictionary where Value: RangeReplaceableCollection {
public mutating func append(element: Value.Iterator.Element, toValueOfKey key: Key) -> Value? {
var value: Value = self[key] ?? Value()
value.append(element)
self[key] = value
return value
}
}
self.orderArray.append(element: name2 as! String, toValueOfKey: "name")
but i facing new problem with Firebase
like that
2019-04-03 00:56:48.969048+0200 Ml Matba5[1809:376762] *** Terminating app
due to uncaught exception 'InvalidPathValidation', reason:
'(child:) Must be a non-empty string and not contain '.' '#' '$' '[' or ']''
*** First throw call stack:
thank you guys
have a good day

Inherit from EKCalendarItem

Because EKEvent can not hold extra properties, I was thinking of creating my own class Event and inherit from EKCalendarItem (same as EKEvent class).
But I get a FrozenClass error, which is quite new to me. Does anybody have any idea of what that means? EKCalendarItem is an open class, so as far as I know I should be able to inherit from that. Or... am I wrong here?
The exact error:
'+[MyApp.Event frozenClass]: unrecognized selector sent to class
0x105667068'
My code:
class Event: EKCalendarItem {
// MARK: - Properties
var id: String
var startDate: Date
var endDate: Date
var isAllDay: Bool
// MARK: - Inits
init?(id: String, dictionary: [String: Any]) {
guard
let title = dictionary["title"] as? String,
let startDate = dictionary["startDate"] as? Timestamp,
let endDate = dictionary["endDate"] as? Timestamp,
let isAllDay = dictionary["isAllDay"] as? Bool
else { return nil }
self.id = id
self.startDate = startDate.dateValue()
self.endDate = endDate.dateValue()
self.isAllDay = isAllDay
super.init()
self.location = dictionary["location"] as? String
self.title = title
self.notes = dictionary["notes"] as? String
}
convenience init?(snapshot: QueryDocumentSnapshot) {
self.init(id: snapshot.documentID, dictionary: snapshot.data())
}
}

Missing argument for parameter 'dictionary' in call

This is my NSObject class file that I am using to populate my collectionView cell. I am fetching my data from firebase and populating the collectionViewCell with it. Xcode is giving this error "Missing argument for parameter 'dictionary' in call" I have tried all I can but I could not figure out what is missing. What is causing this error and how can I fix it?
class BusinessCategory: NSObject {
var ref: FIRDatabaseReference!
var name: String?
var logo: String?
var featurebusiness: [SampleBusinesses]?
var type: String?
init(dictionary: [String: Any]) {
self.name = dictionary["BusinessName"] as? String ?? ""
self.logo = dictionary["logo"] as? String ?? ""
}
static func sampleBusinessCategories() -> [BusinessCategory] {
var FinancialInstitutionCatergory = BusinessCategory()
FinancialInstitutionCatergory.name = "Financial Institutions"
var featurebusiness = [SampleBusinesses]()
//logic
FIRDatabase.database().reference().child("BusinessCategories/Banks").observeSingleEvent(of: .childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let financeApp = SampleBusinesses()
financeApp.setValuesForKeys(dictionary)
financeApp.name = dictionary["BusinessName"] as? String
featurebusiness.append(financeApp)
}
FinancialInstitutionCatergory.featurebusiness = featurebusiness
print(snapshot)
}, withCancel: nil)
return [FinancialInstitutionCatergory]
}
}
The error is stating you need to include the dictionary parameter in whatever line has the error; an example might look something like this:
var FinancialInstitutionCatergory = BusinessCategory(dictionary: [String : Any])
It's unclear which line in your code has the error; you'll need to include the parameter somewhere.

Swift Cannot assign through subscript: subscript is get only

I am fairly new to the Swift syntax and am receiving this error with my code "Cannot assign through subscript: subscript is get only"
This is from the line: friendDictionary[(friendUID as? String)!] = ["name": friendsData!["name"]]
Any advice on the correct way of doing it would be very helpful.
func getFriendsUIDs() {
if FBSDKAccessToken.currentAccessToken() == nil {
print("failed to start graph request")
return
}else{
}
if FBSDKAccessToken.currentAccessToken() != nil {
}
let parameters = ["fields": "name, id, picture"]
FBSDKGraphRequest(graphPath: "/me/friends", parameters: parameters).startWithCompletionHandler {
(NSURLConnection, result, requestError) in
let friendIds = result["id"] as? NSDictionary
let friendsData = friendIds!["data"] as? [NSDictionary]
var ref: FIRDatabaseReference!
ref = FIRDatabase.database().reference()
ref.child("users").child((FIRAuth.auth()?.currentUser?.uid)!).child("friendUIDs").observeEventType(.Value, withBlock: { (snapshot) in
self.FriendUIDs = NSArray()
self.FriendUIDs = (snapshot.value as? NSArray)!
print(self.FriendUIDs)
var friendDictionary = NSDictionary()
for friendUID in self.FriendUIDs {
friendDictionary[(friendUID as? String)!] = ["name": friendsData!["name"]]
}
self.fetchFriendFeed(friendDictionary)
}) { (error) in
print(error.localizedDescription)
}
}
}
func fetchFriendFeed(friendDictionary: NSDictionary) {
var ref: FIRDatabaseReference!
ref = FIRDatabase.database().reference()
for friendUID in FriendUIDs {
ref.child("users").child(friendUID as! String).child("Agenda").observeEventType(.ChildAdded, withBlock: { (snapshot) in
print(snapshot)
if let dictionary = snapshot.value as? [String: AnyObject] {
let friendPost = FriendPost()
friendPost.picture = friendDictionary[friendUID as! String]? ["picture"] as? String
friendPost.activity = dictionary["activity"] as? String
friendPost.date = dictionary["date"] as? String
friendPost.time = dictionary["time"] as? String
friendPost.friendname = friendDictionary[friendUID as! String]? ["name"] as? String
self.friendPosts.append(friendPost)
dispatch_async(dispatch_get_main_queue(), {
self.collectionView?.reloadData()
Nothing to do with Swift. You've elected to use Objective-C, in effect, by making friendDictionary an NSDictionary. NSDictionary is immutable; you can't assign into it or alter it in any way. That is simply a fact about Objective-C. The Swift var declaration makes no difference to this fact.
A better choice, since you are writing in Swift, would be to use a Swift dictionary, which is [AnyHashable:Any]() (in Swift 3). This will interchange with NSDictionary when you are talking to Objective-C, but it will give you a mutable dictionary because you (rightly) declared it with var.
Have you tried using NSMutableDictionary? That solved the issue for me.
For those who get stuck here, another reason for this happens when you try to assign something that does not conform the actual dictionary, in my example i was doing something like this:
var dict = [Date : UUID]()
let randomUUID = UUID()
dict[randomUUID] = Date.now
whereas I meant to write UUID : Date but I was sleepy so i made a mistake, and Swift gave me a misleading error saying subscript is get-only. So this error also appears with type mismatch for Swift 5.7.

Swift 3: Return from initializer error

I'm getting and error that reads: Return from initializer without initializing all stored properties.
I'm using swift 3 and xcode 8 also firebase as my backend.
import Foundation
import FirebaseDatabase
struct Post {
var ref: FIRDatabaseReference
var key: String!
var username: String!
var postId: String!
var postText: String!
init(username: String, postId: String, postText: String, key: String = ""){
self.username = username
self.postId = postId
self.postText = postText
}//<--- im getting the error right here
init(snapshot: FIRDataSnapshot) {
let values = snapshot.value as! Dictionary<String,String>
self.username = values["username"]
self.postText = values["postText"]
self.postId = values["postId"]
self.ref = snapshot.ref
self.key = snapshot.key
}
func toAnyObject() -> [String: AnyObject]{
return ["username":username as AnyObject, "postText":postText as AnyObject,"postId":postId as AnyObject]
}
}
Any idea on how i can fix this?
The stored property ref is a non-optional type.
According the rules all non-optional properties must be initialized in each provided initializer.
That means you have to assign an initial value to the property or you make the property optional.