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.
Related
After I've updated my project I get this error:
Unexpectedly found nil while unwrapping an Optional value
class Search {
private var _username: String!
private var _userImg: String!
private var _userKey: String!
private var _userRef: DatabaseReference!
var currentUser = KeychainWrapper.standard.string(forKey: "uid")
var username: String {
return _username <- error
}
var userImg: String {
return _userImg
}
var userKey: String{
return _userKey
}
init(username: String, userImg: String) {
_username = username
_userImg = userImg
}
init(userKey: String, postData: Dictionary<String, AnyObject>) {
_userKey = userKey
if let username = postData["username"] as? String {
_username = username
}
if let userImg = postData["userImg"] as? String {
_userImg = userImg
}
_userRef = Database.database().reference().child("messages").child(_userKey)
}
}
It worked fine under Swift 3 and Firebase 3.0.2, but now, where everything is update, it crashes all the time. It's not a duplicate to any other question as it worked all before.
I am not sure I fully understand the question or what exactly is causing the crash (it's probably a missing child node) or what the use case is of the implicitly unwrapped class vars but in response to a comment, here's what I would do in Swift 4, Firebase 4
Leave your Search class as is except change the init to the following (this is shortened to provide context)
init(withSnap: DataSnapshot) {
_userKey = withSnap.key
let dict = withSnap.value as! [String: Any]
_username = dict["username"] as? String ?? "NO USER NAME!"
_userImg = dict["userImg"] as? String ?? "NO IMAGE"
}
and then the Firebase function to get a user (for example) would look like this
let userRef = self.ref.child("users").child("uid_0")
userRef.observeSingleEvent(of: .value, with: { snapshot in
let mySearch = Search(withSnap: snapshot)
print(mySearch.userKey, mySearch.username, mySearch.userImg)
})
You would need to add in the rest of the class code to assign _userRef etc.
The idea here is to provide default values to the required class properties in case one of the Firebase nodes didn't exist and results in nil. i.e. if uid_0 didn't have a Username child node your class would crash (which it is). With the code above, that property would be set to a default value.
And for thoroughness suppose a user node looks like this
users
uid_0: "some string" //the value here is a String, not a Dictionary
that would crash my code. To prevent that, add more error checking in the init
init(withSnap: DataSnapshot) {
_userKey = withSnap.key
if let dict = withSnap.value as? [String: Any] {
_username = dict["username"] as? String ?? "NO USER NAME!"
_userImg = dict["userImg"] as? String ?? "NO IMAGE"
} else {
_username = "No user data"
_userImg = "No user data"
}
}
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.
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
}
}
I'm trying to get some values from the UserProfile node from the dashboard and pass them into global variables to use them globally outside the observe function.
ref.child("UserProfile").child(FIRAuth.auth()!.currentUser!.uid).observeEventType(.Value , withBlock: {snapshot in
if let name = snapshot.value!.objectForKey("name") as? String {
print(name)
}
if let email = snapshot.value!.objectForKey("email") as? String {
print(email)
}
if let phone = snapshot.value!.objectForKey("phone") as? String {
print(phone)
}
if let city = snapshot.value!.objectForKey("city") as? String {
print(city)
}
})
I want to pass them outside the observe function so I can use them globally anywhere in the .swift file.
Since Firebase functions are supposed to be Asynchronous, you need to access these User properties inside the completionBlock of the function. And mind that They will only give retrieved value once the call has been completed.
var globalUserName : String!
var globalEmail : String!
var globalPhone : String!
var globalCity : String!
override func viewWillAppear(animated : Bool){
super.viewWillAppear(animated)
retrieveUserData{(name,email,phone,city) in
self.globalUserName = name
self.globalEmail = email
self.globalPhone = phone
self.globalCity = city
}
}
func retrieveUserData(completionBlock : ((name : String!,email : String!, phone : String!, city : String!)->Void)){
ref.child("UserProfile").child(FIRAuth.auth()!.currentUser!.uid).observeEventType(.Value , withBlock: {snapshot in
if let userDict = snapshot.value as? [String:AnyObject] {
completionBlock(name : userDict["name"] as! String,email : userDict["email"] as! String, phone : userDict["phone"] as! String, city : userDict["city"] as! String)
}
})
}
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.