Loop through an optional object in Swift 4 - ios

I have this code
let dic = snapshot.value as! [String:[String:Any]]
Array(dic.values).forEach {
print($0["fcmToken"])
}
It produce these 3
Optional(c1DdtdDF1Rs:APA91bGJBUD65nidQiFDO90AVNgq0wiMjUaZmZXVJ8c_tYmFe5dkmgweOdO10jzPRlMVZF_qNyWMMsu7EhA5IMVo3jLWvBThDteR7WWUPqau-ZFAHKQPHgI5Vb48vA-_4nwkZCKrOVoT)
Optional(c1DdtdDF1Rs:APA91bGJBUD65nidQiFDO90AVNgq0wiMjUaZmZXVJ8c_tYmFe5dkmgweOdO10jzPRlMVZF_qNyWMMsu7EhA5IMVo3jLWvBThDteR7WWUPqau-ZFAHKQPHgI5Vb48vA-_4nwkZCKrOVoT)
Optional(c1DdtdDF1Rs:APA91bGJBUD65nidQiFDO90AVNgq0wiMjUaZmZXVJ8c_tYmFe5dkmgweOdO10jzPRlMVZF_qNyWMMsu7EhA5IMVo3jLWvBThDteR7WWUPqau-ZFAHKQPHgI5Vb48vA-_4nwkZCKrOVoT)
I want to loop through them and add a simple if-check.
I tried
let dic = snapshot.value as! [String:[String:Any]]
Array(dic.values).forEach {
print($0["fcmToken"])
if($0["fcmToken"] != fcmToken) {
print("token is not match detected")
}
}
I kept getting
Binary operator '!=' cannot be applied to operands of type 'Any?' and 'String?'
How would one go about debugging this further?

You have:
let dic = snapshot.value as! [String:[String:Any]]
Array(dic.values).forEach {
print($0["fcmToken"])
if($0["fcmToken"] != fcmToken) {
print("token is not match detected")
}
}
But it’s giving you a compile error.
Assuming that this line is working:
let dic = snapshot.value as! [String:[String:Any]]
I'd write the rest like this:
for v in dic.values {
if let token = v["fcmtoken"] as? String, token != fcmtoken {
print("token \(token) is not match detected")
}
}
The effect is the same and there’s no error.

You can try
let dic = snapshot.value as! [String:[String:Any]]
let tokens = Array(dic.values).map { $0["fcmToken"] as! String }
let exists = tokens.contains(fcmToken)
Your problem as $0["fcmToken"] is of type Any? that can't compared with type String? ( fcmToken )
let dic = snapshot.value as! [String:[String:Any]]
Array(dic.values).forEach {
print($0["fcmToken"])
if let token = $0["fcmToken"] as? String , token != fcmToken {
print("token is not match detected")
}
// or
if ($0["fcmToken"] as? String) != fcmToken {
print("token is not match detected")
}
}
You can savely use
guard let dic = snapshot.value as? [String: [String:Any]] else {
return
}
but it won't function when the value is nil

Related

Swift future publisher error when getting data from firebase

I'm new to swift language, but now I'm developing app with swift and firebase.
I'm using realtime database and while making two identical functions for getting data one is working and one is not.
This is the working one:
func getRoom(admin: String) -> AnyPublisher<Room, Error> {
Deferred {
Future { promise in
Database.database().reference().child("rooms/\(admin)")
.getData { [self] error, snapshot in
guard error == nil else {
promise(.failure(error!))
print(error!.localizedDescription)
return;
}
let value = snapshot.value as? [String:[String:Any]]
for (key, room) in value ?? [:] {
if (key == admin){
let admin = room["admin"] as? [String:Any]
let subjects = room["subjects"] as? [String]
let difficulties = room["difficulties"] as? [String]
let users = room["users"] as? [[String:Any]]
let questions = room["questions"] as? [[String:Any]]
let isGameStarted = room["is_game_started"] as? String
let room = Room(admin: dictionaryToUser(userDict: admin!), subjects: subjects!, difficutlies: difficulties!, users: dictionaryToUsersArr(usersArrDict: users!), questions: dictionaryToQuestionArr(questionsArrDict: questions!), is_game_started: isGameStarted!)
promise(.success(room))
}
}
}
}
}
.eraseToAnyPublisher()
}
And this is not working:
func getRoomUsersFromRoom(admin: String) -> AnyPublisher<[RoomUser], Error> {
var roomUsers: [RoomUser] = []
Deferred {
Future { promise in
Database.database().reference()
.child("rooms/\(admin)")
.getData { error, snapshot in
guard error == nil else {
promise(.failure(error!))
print(error!.localizedDescription)
return;
}
let value = snapshot.value as? [String:[String:Any]]
for (key, room) in value ?? [:] {
if (key == admin){
let users = room["users"] as? [[String:Any]]
for i in 0..<users!.count {
roomUsers.append(RoomUser(username: users![i]["username"] as! String, gamePoints: users![i]["room_points"] as! Int))
}
promise(.success(roomUsers))
}
}
promise(.success(roomUsers))
}
}
}
.eraseToAnyPublisher()
}
The errors in the second one are on the line with the Future, telling:
"Generic parameter 'Failure' could not be inferred"
"Generic parameter 'Output' could not be inferred"
It suggests me to put Future<Any, Error> and the error is gone but then I have warning on "eraseToAnyPublisher()", which I think is not good.
What is difference between the functions and any ideas how to solve this?
Thanks in advance

How to print the public details like first name, last name or email in Facebook SDK 4.18.0 in swift3?

I am integrating facebook login in Swift3 language in iOS using FBSDK4.18.0.Below is the following code: But it does
not prints the results including
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
print("User Logged In")
if ((error) != nil)
{
// Process error
}
else if result.isCancelled {
// Handle cancellations
}
else {
// If you ask for multiple permissions at once, you
// should check if specific permissions missing
if result.grantedPermissions.contains("public_profile")
{
// Do work
// let strFirstName: [String: Any]? = (result.objectForKey("first_name") as? String)!
// let strLastName: String = (result.objectForKey("last_name") as? String)!
// let strPictureURL: String = (result.objectForKey("picture")?.objectForKey("data")?.objectForKey("url") as? String)!
if let dic = result as? [String: Any]
{ if let strFirstName = dic["first_name"] as? String, let strLastName = dic["last_name"] as? String
{
print("\(strFirstName) \(strLastName)")
}
}
}
}
}
It also shows the "Cast from 'FBSDKLoginManagerLoginResult!' to unrelated type '[String : Any]' always fails" warning at "if let dic = result as? [String: Any]"
You should use AnyObject and not Any. More on it can be found here:
if let dic = result as? [String: AnyObject] {
if let strFirstName = dic["first_name"] as? String, let strLastName = dic["last_name"] as? String
{
print("\(strFirstName) \(strLastName)")
}
}

Swift Firebase Access child snapshot data

I am currently trying to access data from a child snapshot in Swift. Here is my code that I have (which worked before the Swift 3/Firebase update):
if let achievements = snapshot1.childSnapshotForPath("Achievements").children.allObjects as? [FIRDataSnapshot] {
if achievements.count != 0 {
if let val = achievements[0].value!["somevalue"] as? Int {
self.dict["somevalue"] = val
}
}
So what I am trying to do here, is to create a variable of a child snapshot (achievements), and access child snapshot data from it. The achievements[0] will simply return the very first value. However, this doesn't seem to work. How should I approach this?
I am currently doing this inside a snapshot already (of 'observeType:.ChildAdded')
My Firebase DB looks like this:
Achievements{
randomId1 {
somevalue : somevalue
}
randomId2 {
somevalue2 : somevalue2
}
}
Updated code:
func loadData() {
ref.child("Players").observe(FIRDataEventType.childAdded) { (snapshot:FIRDataSnapshot) in
if let value = snapshot.value as? [String:AnyObject], let username = value["Username"] as? String {
}
if let value = snapshot.value as? [String:AnyObject], let ranking = value["Rank"] as? String {
}
if let childSnapshot = snapshot.childSnapshot(forPath: "Achievements").children.allObjects as? [FIRDataSnapshot] {
if childSnapshot.count != 0 {
if let achievement1 = childSnapshot[0].value!["Rookie"] as? String {
print(achievement1)
}
}
}
}
}
JSON Tree:
Players {
PlayerID {
Username
Rank
Achievements {
Rookie: yes
}
}
Try :-
if let childSnapshot = snapshot.childSnapshot(forPath: "Achievements") as? FIRDataSnapshot{
if let achievementDictionary = childSnapshot.value as? [String:AnyObject] , achievementDictionary.count > 0{
if let achieveMedal = achievementDictionary["Rookie"] as? String {
print(achieveMedal)
}
}
}

Ambiguous use of subscript. Array Swift IOS

I try to compile on device but i get this error. Any help?. In the simulator works perfectly.
I get an ambiguous use of subscript error in the following code and was hoping somebody else has encountered this and know the fix.
case .Success:
if response.response?.statusCode == 200 {
print ("Respuesta 200")
if let value = response.result.value {
let respuestaJSON = JSON(value)
let objsonUSUARIOS = respuestaJSON["d"].object
let arrayUsuarios = objsonUSUARIOS["results"]!
//print ("Usuarios: ",String(arrayUsuarios))
for i in 0 ..< arrayUsuarios!.count{
let boletines = boletinJSON()
if let item = arrayUsuarios![i] as? [String: AnyObject]{
)
if let person = item["Title"] as? String
{
boletines.name = person
}
if let person = item["Portada"] as? String
{
boletines.imagen = person
}
if let person = item["Created"] as? String
{
boletines.fecha = person
}
if let person = item["AttachmentFiles"] as? [String: AnyObject] {
if let itemAttach = person["__deferred"] as? [String: AnyObject]{
if let itemdeferred = itemAttach["uri"] as? String {
boletines.urldescarga = itemdeferred
}
}
}
self.boletin.append(boletines)
self.view.hideToastActivity()
}
}
}
self.tableView.reloadData()
// self.view.hideToastActivity()
}
Inform the compiler what the intermediary object objsonUSUARIOS is of type
let objsonUSUARIOS = respuestaJSON["d"].object
After the above statement, the compiler does not know what kind of object he is dealing with. So make sure that you can actually do all the casting as below
let objsonUSUARIOS = respuestaJSON["d"].object as! Dictionary
let arrayUsuarios = objsonUSUARIOS["results"]! as! Array
The problem is that you have not specified the type of object arrayUsuarios is Array, so try to explicit type cast the arrayUsuarios Array
let arrayUsuarios = objsonUSUARIOS["results"] as! [[String: AnyObject]]

Extracting values from anyobject dictionary into array

My other question was marked as being identical to another but it didn't answer the problem I was having.
Here is the code:
if status == "OK" {
self.selectedRoute = (dictionary["routes"] as! Array<Dictionary<NSObject, AnyObject>>)[0]
self.overviewPolyline = self.selectedRoute["overview_polyline"] as! Dictionary<NSObject, AnyObject>
let legs = self.selectedRoute["legs"] as! Array<Dictionary<NSObject, AnyObject>>
let steps = legs[0]["steps"]!
for i in 0...steps.count - 1 {
let step_coordinate = steps[i]["start_location"]!
print(step_coordinate!["lat"]!!)
}
}
The print statement gives this result
40.7609205
40.7640121
40.7595325
40.7501637
40.7481923
40.7393448
40.7252038
40.7225337
40.718295
but if I swap the print statement out to grab the values and put them in an array I get the fatal error: found nil.
Can someone explain why this is the case? How can I grab these values if not through a for loop?
Here's a cleaner version of your code.
Rules:
Don't force unwrap anything!
Optionally cast values coming from [NSObject: AnyObject] lookups.
Use guard statements and if let to safely unwrap optionals.
Don't index arrays that might be empty without checking first.
if status == "OK" {
guard let routes = dictionary["routes"] as? [[NSObject: AnyObject]] else { return }
self.selectedRoute = routes.first ?? [:]
self.overviewPolyline = self.selectedRoute["overview_polyline"] as? [NSObject: AnyObject] ?? [:]
guard let legs = self.selectedRoute["legs"] as? [[NSObject: AnyObject]] else { return }
let firstleg = legs.first ?? [:]
guard let steps = firstleg["steps"] as? [[NSObject: AnyObject]] else { return }
for step in steps {
if let step_coordinate = step["start_location"] as? [NSObject: AnyObject] {
if let lat = step_coordinate["lat"] as? Double {
print(lat)
// append lat to array of lats
lats.append(lat)
}
}
}
}

Resources