I'm trying to save CNContact details into my UserDefaults but it fails.
Any other way I could save CNContact ?
struct User {
var firstName: String = ""
var lastName: String = ""
var email: String = ""
var phoneNumber: String = ""
var company: String = ""
var assistantContact: CNContact?
init(firstName: String, lastName: String, email: String, phoneNumber: String, company: String, assistantContact: CNContact? = nil) {
self.firstName = firstName
self.lastName = lastName
self.email = email
self.phoneNumber = phoneNumber
self.company = company
self.assistantContact = assistantContact
}
func encode() -> Dictionary<String, AnyObject> {
var dictionary : Dictionary = Dictionary<String, AnyObject>()
dictionary["firstName"] = firstName as AnyObject?
dictionary["lastName"] = lastName as AnyObject?
dictionary["email"] = email as AnyObject?
dictionary["phoneNumber"] = phoneNumber as AnyObject?
dictionary["company"] = company as AnyObject?
dictionary["assistantContact"] = assistantContact as AnyObject?
return dictionary
}
init(dictionary: Dictionary<String, AnyObject>) {
if let firstName = dictionary["firstName"] as? String {
self.firstName = firstName
}
if let lastName = dictionary["lastName"] as? String {
self.lastName = lastName
}
if let email = dictionary["email"] as? String {
self.email = email
}
if let phoneNumber = dictionary["phoneNumber"] as? String {
self.phoneNumber = phoneNumber
}
if let company = dictionary["company"] as? String {
self.company = company
}
if let assistantContact = dictionary["assistantContact"] as? CNContact {
self.assistantContact = assistantContact
}
}
}
First Encode Contacts Array using.
let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: contactsArray)
Now save encodedData in UserDefaults.
For decode contacts array,
if let contacts: [CNContact] = decodedData as? [CNContact] {
//Decoded Contacts Array
}
Related
I am following a pinterest style UICollectionViewLayout tutorial, however the tutorial has a Photos Model and my photos are in URL format so I am not able to have a return function in the delegate method. How can I return my image to fill this requirement. image
extension PagesCollectionViewController : PinterestLayoutDelegate {
func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath:IndexPath) -> CGFloat {
return userArray[indexPath.row].photoURL
// return photos[indexPath.item].image.size.height
}
import Foundation
import Firebase
import FirebaseDatabase
struct Users {
var email: String!
var uid: String!
var ref: DatabaseReference!
var location: String?
var photoURL: String!
var biography: String?
var key: String?
var name: String!
var phoneNumber: NSNumber?
var password: String!
init(snapshot: DataSnapshot) {
if let snap = snapshot.value as? [String: Any]{
self.password = snap["password"] as! String
self.email = snap["email"] as! String
self.uid = snap["uid"] as! String
self.phoneNumber = Double(snap["phoneNumber"] as! String) as? NSNumber
self.location = snap["location"] as! String
self.photoURL = snap["photoURL"] as! String
self.biography = snap["biography"] as! String
self.name = snap["firstLastName"] as! String
}
}
init(data: NSDictionary) {
self.password = data.value(forKey: "password") as! String
self.email = data.value(forKey: "email") as! String
self.uid = data.value(forKey: "uid") as! String
self.phoneNumber = Double(data.value(forKey: "phoneNumber") as! String) as? NSNumber
self.location = data.value(forKey: "location") as! String
self.photoURL = data.value(forKey: "photoURL") as! String
self.biography = data.value(forKey: "biography") as! String
self.name = data.value(forKey: "firstLastName") as! String
}
init(email: String, uid: String) {
self.email = email
self.uid = uid
self.ref = Database.database().reference()
}
}
I'm comfortable with initializing objects in general but my method only seems to work when all parameters must exist on the database. I have looked at this which works. But I now don't know how to initialize it with a nest array.
This is how I would normally initialise an object:
class User {
var firstName: String
var lastName: String
var summary: String?
var groups = [Group]()
var ref: DatabaseReference?
var key: String
init?(from snapshot: DataSnapshot) {
let snapshotValue = snapshot.value as? [String: Any]
guard let firstName = snapshotValue?["firstName"] as? String, let lastName = snapshotValue?["lastName"] as? String, let summary = snapshotValue?["summary"] as? String else { return nil }
self.firstName = firstName
self.lastName = lastName
self.summary = summary
self.key = snapshot.key
self.groups(snapshot: snapshot.childSnapshot(forPath: "groups"))
}
func groups(snapshot: DataSnapshot) {
for child in snapshot.children {
guard let group = child as? DataSnapshot else { continue }
}
}
Just don't make the optional properties a part of that guard (that's what prevents the execution to finish it:
init?(from snapshot: DataSnapshot) {
let snapshotValue = snapshot.value as? [String: Any]
guard let firstName = snapshotValue?["firstName"] as? String,
let lastName = snapshotValue?["lastName"] as? String else { return nil }
self.firstName = firstName
self.summary = snapshotValue?["summary"] as? String
self.key = snapshot.key
self.groups(snapshot: snapshot.childSnapshot(forPath: "groups"))
}
Optionally, you can use if let syntax:
if let summary = snapshotValue?["summary"] as? String {
self.summary = summary
}
But in this case this is simpler:
self.summary = snapshotValue?["summary"] as? String
I want to fetch data, I have done this multiple times but for some reason it is not working and I see no reason as to why.
My code for fetching the data
func fetchCurrentUserInfo() {
let currentUser = Auth.auth().currentUser!
let currentUserRef = dataBaseRef.child("users").child(currentUser.uid)
currentUserRef.observeSingleEvent(of: .value, with: { (snapshot) in
let user = UserClass(snapshot: snapshot)
self.downloadImageFromFirebase(urlString: user.photoURL!)
self.userName.text = user.getFullName()
//SD Cache
self.userProfileImage.sd_setImage(with: URL(string: user.photoURL!), placeholderImage: UIImage(named: "UserImageTemplate"))
}) { (error) in
let alert = SCLAlertView()
_ = alert.showError("OOPS!", subTitle: error.localizedDescription)
}
}
My user class file
struct UserClass {
var firstName: String?
var email: String?
var photoURL: String?
var uid: String?
var ref: DatabaseReference!
var key: String?
var lastName: String?
var accountType: String?
init(snapshot: DataSnapshot){
key = snapshot.key
ref = snapshot.ref
accountType = (snapshot.value! as! NSDictionary)["Account Type"] as? String
firstName = (snapshot.value! as! NSDictionary)["First Name"] as? String
email = (snapshot.value! as! NSDictionary)["email"] as? String
uid = (snapshot.value! as! NSDictionary)["uid"] as? String
photoURL = (snapshot.value! as! NSDictionary)["photoURL"] as? String
lastName = (snapshot.value! as! NSDictionary)["Last Name"] as? String
}
func getFullName() -> String {
return ("\(firstName!) \(lastName!)")
}
}
}
I have set the read and write rules to true. When I call the fetchCurrentUserInfo function, it returns all the data for the first name, last name, key, etc. but it returns the photo URL, UID or email as nil giving me the error: fatal error: unexpectedly found nil while unwrapping an Optional value.
Your crash log says it all. You're trying to force unwrap an optional variable by as! casting. Make sure you have valid values in your snapshot.
Also, a better model would like so, this is safer:
struct UserClass {
var firstName: String!
var email: String!
var photoURL: String!
var uid: String!
var ref: DatabaseReference!
var key: String!
var lastName: String!
var accountType: String!
init?(snapshot: DataSnapshot?) {
guard let value = snapshot?.value as? [String: AnyObject],
let accountType = value["Account Type"] as? String,
let firstName = value["First Name"] as? String,
let email = value["email"] as? String,
let uid = value["uid"] as? String,
let photoURL = value["photoURL"] as? String,
let lastName = value["Last Name"] as? String else {
return nil
}
self.key = snapshot?.key
self.ref = snapshot?.ref
self.accountType = accountType
self.firstName = firstName
self.email = email
self.uid = uid
self.photoURL = photoURL
self.lastName = lastName
}
func getFullName() -> String {
return ("\(firstName!) \(lastName!)")
}
}
I am getting an error that in the line "self.email = (snapshot.value as! NSDictionary)["email"] as! String" saying that it could not cast value of type 'NSNull'. How do I fix the error? I thought that since I have a function toAnyObject that it would convert everything to a String.
struct User {
var email: String!
var uid: String!
var ref: DatabaseReference!
var key: String = ""
init(snapshot: DataSnapshot) {
self.email = (snapshot.value as! NSDictionary)["email"] as! String
self.uid = (snapshot.value as! NSDictionary)["uid"] as! String
self.ref = snapshot.ref
self.key = snapshot.key
}
init(email: String, uid: String) {
self.email = email
self.uid = uid
self.ref = Database.database().reference()
}
func toAnyObject() -> [String: Any] {
return ["email":self.email, "uid":self.uid]
}
}
As El Captain v2.0 pointed out, don´t force unwrap a value as it might be nil and you´ll get a crash. Use if let instead:
// if snap has a value, then you can use the value. Otherwise not, you can call an else if you want to.
if let snap = snapshot.value as? [String:Any] {
self.email = snap["email"] as! String
}
And I would skip the as! String too and would have done it like this instead, incase of you don´t get the email value.
if let snap = snapshot.value as? [String:Any], let email = snap["email"] as? String {
// Use email in here now
print(email)
}
So if you have other fields you want to get, just add them into the if-statement.
struct User {
var email: String!
var uid: String!
var ref: DatabaseReference!
var key: String = ""
init(snapshot: DataSnapshot){
self.email = (snapshot.value as! NSDictionary)["email"] as! String
self.uid = (snapshot.value as! NSDictionary)["uid"] as! String
self.ref = snapshot.ref
self.key = snapshot.key
}
init(email: String, uid: String){
if let snap = snapshot.value as? [String:Any] {
// Do not unwrap forcefully, instead use as mentioned below
// so that in case snap["email"] gives null that could be
//handled.
//Also please check that whether you have "firstname" var
//present in not in your code and dictionary both.
self.email = snap["email"] as? String ?? "" //Provide some default value or empty string
}
self.uid = uid
self.ref = Database.database().reference()
}
func toAnyObject() -> [String: Any]{
return ["email":self.email, "uid":self.uid]
}
}
I have created 'struct FireBaseData' which enables me to retrieve data from Firebase. I would like to convert the data into an array of dictionaries and then output the content to Desktop in a .txt file.
How can I convert self.bookingInfo to an array of dictionaries?
func startObservingDB() {
dbRef.child(FullData.uid!).observe(.value, with: { (snapshot: FIRDataSnapshot) in
// an instance of FireBaseData holding all bookings under currentUid
var newBookingInfo = [FireBaseData]()
//iterate over all children under /FullData.uid! path
for customer in snapshot.children {
//the customer node starting with cus...
let customerObject = customer as! FIRDataSnapshot
//customer key
self.customerKey = customerObject.key
print("this is the Stripe customer that can be charged \(customerObject.key)")
//now iterate over each booking which is located under customerObject in Firebase
for booking in customerObject.children {
// after each iteration through snapshot.children, create an instance of FireBaseData with 'booking' for the current iteration & assign it to bookingItem
var bookingItem = FireBaseData(snapshot: booking as! FIRDataSnapshot)
//assign key of the parent to each booking
bookingItem.Key = self.customerKey
// append the bookingItem after each iteration to newBookingInfo array
newBookingInfo.append(bookingItem)
} // end of for booking in myCustomer
} // end of for customer in snapshot.children
//assign newBookingInfo to global variable
self.bookingInfo = newBookingInfo
// sort the array in place so that the most recent date will appear first
self.bookingInfo.sort(by: {(DateAndTimeObject_1,DateAndTimeObject_2) -> Bool in
DateAndTimeObject_1.TimeStampDateAndTime > DateAndTimeObject_2.TimeStampDateAndTime
})
let arrayOfDictionary = self.bookingInfo.flatMap { $0.toAnyObject() as? [String:Any] }
let stringSeparated = arrayOfDictionary.joined(separator: "-")
print("stringSeparated \(stringSeparated)")
self.tableView.reloadData()
}, withCancel: { (Error:Any) in
print("Error firebase \(Error)")
})
} // end of startObservingDB()
//Model to retrive data
import Foundation
import UIKit
import Firebase
import FirebaseDatabase
struct FireBaseData {
// Create our Firebase Data model
// get arbitrary data
var FirebaseUserID:String!
var PaymentID:String!
var BookingAmount:String!
var BookingNumber:String!
var Key:String!
var PostCode:String!
var SelectedBathRow:Int!
var SelectedBedRow:Int!
var DateAndTime:String!
var TimeStampDateAndTime:Int!
var TimeStampBookingSavedInDB:Int!
var BookingStatusClient:Bool!
var BookingStatusAdmin:Bool!
var BookingCompleted:Bool!
//used in RootController and RootController1 to determine if the booking has already been cancelled or not
var CostToCancelClient:String!
var CostToCancelAdmin:String!
var CostToRescheduleAdmin:String!
var CostToRescheduleClient:String!
var DoormanOption:String!
var EntryInstructions:String!
var NoteInstructions:String!
var FrequencyName:String!
var FrequecyAmount:Int!
var insideCabinets:Bool!
var insideFridge:Bool!
var insideOven:Bool!
var laundryWash:Bool!
var interiorWindows:Bool!
var SuppliesName:String!
var SuppliesAmount:Int!
var FullName:String!
var FlatNumber:String!
var StreetAddress:String!
var PhoneNumber:String!
var EmailAddress:String!
let Ref:FIRDatabaseReference?
init(BookingAmount:String,
BookingNumber:String,
PostCode:String,
SelectedBathRow:Int,
SelectedBedRow:Int,
DateAndTime:String,
TimeStampDateAndTime:Int,
BookingStatusClient:Bool,
BookingStatusAdmin:Bool,
BookingCompleted:Bool,
FrequencyName:String,
FrequecyAmount:Int,
insideCabinets:Bool,
insideFridge:Bool,
insideOven:Bool,
laundryWash:Bool,
interiorWindows:Bool,
FullName:String,
SuppliesName:String,
SuppliesAmount:Int,
FlatNumber:String,
StreetAddress:String,
PhoneNumber:String,
EmailAddress:String,
Key:String = "") {
self.BookingAmount = BookingAmount
self.BookingNumber = BookingNumber
self.Key = Key
self.PostCode = PostCode
self.SelectedBathRow = SelectedBathRow
self.SelectedBedRow = SelectedBedRow
self.DateAndTime = DateAndTime
self.TimeStampDateAndTime = TimeStampDateAndTime
self.BookingStatusClient = BookingStatusClient
self.BookingStatusAdmin = BookingStatusAdmin
self.BookingCompleted = BookingCompleted
self.FrequencyName = FrequencyName
self.FrequecyAmount = FrequecyAmount
self.insideCabinets = insideCabinets
self.insideFridge = insideFridge
self.insideOven = insideOven
self.laundryWash = laundryWash
self.interiorWindows = interiorWindows
self.FullName = FullName
self.SuppliesName = SuppliesName
self.SuppliesAmount = SuppliesAmount
self.FlatNumber = FlatNumber
self.StreetAddress = StreetAddress
self.PhoneNumber = PhoneNumber
self.EmailAddress = EmailAddress
self.Ref = nil
}
// Content
// receive data from our firebase database
init(snapshot:FIRDataSnapshot){
if let firebaseUserID = (snapshot.value! as? NSDictionary)?["FirebaseUserID"] as? String {
FirebaseUserID = firebaseUserID
}
if let paymentID = (snapshot.value! as? NSDictionary)?["PaymentID"] as? String {
PaymentID = paymentID
}
if let BookingAmountContent = (snapshot.value! as? NSDictionary)?["BookingAmount"] as? String {
BookingAmount = BookingAmountContent
}
if let BookingNumberContent = (snapshot.value! as? NSDictionary)?["BookingNumber"] as? String {
BookingNumber = BookingNumberContent
}
Key = snapshot.key
Ref = snapshot.ref
if let PostCodeContent = (snapshot.value! as? NSDictionary)?["PostCode"] as? String {
PostCode = PostCodeContent
}
if let SelectedBathRowContent = (snapshot.value! as? NSDictionary)?["SelectedBathRow"] as? String {
SelectedBathRow = Int(SelectedBathRowContent)
}
if let SelectedBedRowContent = (snapshot.value! as? NSDictionary)?["SelectedBedRow"] as? String {
SelectedBedRow = Int(SelectedBedRowContent)
}
if let DateAndTimeContent = (snapshot.value! as? NSDictionary)?["DateAndTime"] as? String {
DateAndTime = DateAndTimeContent
}
if let TimeStampDateAndTimeContent = (snapshot.value! as? NSDictionary)?["TimeStampDateAndTime"] as? String {
TimeStampDateAndTime = Int(TimeStampDateAndTimeContent)
}
if let TimeStampBookingSavedInDBContent = (snapshot.value! as? NSDictionary)?["TimeStampBookingSavedInDB"] as? String {
TimeStampBookingSavedInDB = Int(TimeStampBookingSavedInDBContent)
}
if let BookingStatusClientContent = (snapshot.value! as? NSDictionary)?["BookingStatusClient"] as? String{
BookingStatusClient = Bool(BookingStatusClientContent)
}
if let BookingStatusAdminContent = (snapshot.value! as? NSDictionary)?["BookingStatusAdmin"] as? String {
BookingStatusAdmin = Bool(BookingStatusAdminContent)
}
if let BookingCompletedContent = (snapshot.value! as? NSDictionary)?["BookingCompleted"] as? String {
BookingCompleted = Bool(BookingCompletedContent)
}
if let costToCancelCient = (snapshot.value! as? NSDictionary)?["CostToCancelClient"] as? String {
CostToCancelClient = costToCancelCient
}
if let costToCancelAdmin = (snapshot.value! as? NSDictionary)?["CostToCancelAdmin"] as? String {
CostToCancelAdmin = costToCancelAdmin
}
if let costToRescheduleAdmin = (snapshot.value! as? NSDictionary)?["CostToRescheduleAdmin"] as? String {
CostToRescheduleAdmin = costToRescheduleAdmin
}
if let costToRescheduleClient = (snapshot.value! as? NSDictionary)?["CostToRescheduleClient"] as? String {
CostToRescheduleClient = costToRescheduleClient
}
if let doormanOption = (snapshot.value! as? NSDictionary)?["DoormanOption"] as? String {
DoormanOption = doormanOption
}
if let entryInstructions = (snapshot.value! as? NSDictionary)?["EntryInstructions"] as? String {
EntryInstructions = entryInstructions
}
if let noteInstructions = (snapshot.value! as? NSDictionary)?["NoteInstructions"] as? String {
NoteInstructions = noteInstructions
}
if let FrequencyNameContent = (snapshot.value! as? NSDictionary)?["FrequencyName"] as? String {
FrequencyName = FrequencyNameContent
}
if let FrequecyAmountContent = (snapshot.value! as? NSDictionary)?["FrequecyAmount"] as? String {
FrequecyAmount = Int(FrequecyAmountContent)
}
if let insideCabinetsContent = (snapshot.value! as? NSDictionary)?["InsideCabinets"] as? String {
insideCabinets = Bool(insideCabinetsContent)
}
if let insideFridgeContent = (snapshot.value! as? NSDictionary)?["InsideFridge"] as? String {
insideFridge = Bool(insideFridgeContent)
}
if let insideOvenContent = (snapshot.value! as? NSDictionary)?["InsideOven"] as? String {
insideOven = Bool(insideOvenContent)
}
if let laundryWashContent = (snapshot.value! as? NSDictionary)?["LaundryWash"] as? String {
laundryWash = Bool(laundryWashContent)
}
if let interiorWindowsContent = (snapshot.value! as? NSDictionary)?["InteriorWindows"] as? String {
interiorWindows = Bool(interiorWindowsContent)
}
if let FullNameContent = (snapshot.value! as? NSDictionary)?["FullName"] as? String {
FullName = FullNameContent
}
if let SuppliesNameContent = (snapshot.value! as? NSDictionary)?["SuppliesName"] as? String {
SuppliesName = SuppliesNameContent
}
if let SuppliesAmountContent = (snapshot.value! as? NSDictionary)?["SuppliesAmount"] as? String {
SuppliesAmount = Int(SuppliesAmountContent)
}
if let FlatNumberContent = (snapshot.value! as? NSDictionary)?["FlatNumber"] as? String {
FlatNumber = FlatNumberContent
}
if let StreetAddressContent = (snapshot.value! as? NSDictionary)?["StreetAddress"] as? String {
StreetAddress = StreetAddressContent
}
if let PhoneNumberContent = (snapshot.value! as? NSDictionary)?["PhoneNumber"] as? String {
PhoneNumber = PhoneNumberContent
}
if let EmailAddressContent = (snapshot.value! as? NSDictionary)?["EmailAddress"] as? String {
EmailAddress = EmailAddressContent
}
}
func toAnyObject() -> AnyObject {
var someDict = [String : Any]()
someDict["FirebaseUserID"] = self.FirebaseUserID as AnyObject?
someDict["PaymentID"] = self.PaymentID as AnyObject?
someDict["BookingAmount"] = self.BookingAmount as AnyObject?
someDict["BookingNumber"] = self.BookingNumber as AnyObject?
someDict["PostCode"] = self.PostCode as AnyObject?
someDict["SelectedBathRow"] = self.SelectedBathRow as AnyObject?
someDict["SelectedBedRow"] = self.SelectedBedRow as AnyObject?
someDict["DateAndTime"] = self.DateAndTime as AnyObject?
someDict["TimeStampDateAndTime"] = self.TimeStampDateAndTime as AnyObject?
someDict["TimeStampBookingSavedInDB"] = self.TimeStampBookingSavedInDB as AnyObject?
someDict["BookingStatusClient"] = self.BookingStatusClient as AnyObject?
someDict["BookingStatusAdmin"] = self.BookingStatusAdmin as AnyObject?
someDict["BookingCompleted"] = self.BookingCompleted as AnyObject?
someDict["CostToCancelClient"] = self.CostToCancelClient as AnyObject?
someDict["CostToCancelAdmin"] = self.CostToCancelAdmin as AnyObject?
someDict["CostToRescheduleAdmin"] = self.CostToRescheduleAdmin as AnyObject?
someDict["CostToRescheduleClient"] = self.CostToRescheduleClient as AnyObject?
someDict["DoormanOption"] = self.DoormanOption as AnyObject?
someDict["EntryInstructions"] = self.EntryInstructions as AnyObject?
someDict["NoteInstructions"] = self.NoteInstructions as AnyObject?
someDict["FrequencyName"] = self.FrequencyName as AnyObject?
someDict["FrequecyAmount"] = self.FrequecyAmount as AnyObject?
someDict["insideCabinets"] = self.insideCabinets ? "true" : "false"
someDict["insideFridge"] = self.insideFridge ? "true" : "false"
someDict["insideOven"] = self.insideOven ? "true" : "false"
someDict["laundryWash"] = self.laundryWash ? "true" : "false"
someDict["interiorWindows"] = self.interiorWindows ? "true" : false
someDict["FullName"] = self.FullName as AnyObject?
someDict["SuppliesName"] = self.SuppliesName as AnyObject?
someDict["SuppliesAmount"] = self.SuppliesAmount as AnyObject?
someDict["FlatNumber"] = self.FlatNumber as AnyObject?
someDict["StreetAddress"] = self.StreetAddress as AnyObject?
someDict["PhoneNumber"] = self.PhoneNumber as AnyObject?
someDict["EmailAddress"] = self.EmailAddress as AnyObject?
return someDict as AnyObject
}
}
Desired Output as per Nirav request
EmailAddress": johnmm#gmail.com,
"PhoneNumber": 07476953923,
"PaymentID": ch_1ARd6yLCZ34Ur7XG4wAqaH9H,
"BookingAmount": 27
EmailAddress": Chris#gmail.com,
"PhoneNumber": 07476953923,
"PaymentID": ch_1ARd6yLCZ34Ur7XG4wAqaH9H,
"BookingAmount": 27
EmailAddress": Mike#gmail.com,
"PhoneNumber": 07476953923,
"PaymentID": ch_1ARd6yLCZ34Ur7XG4wAqaH9H,
"BookingAmount": 27
What you need is to just use toAnyObject() method to get the dictionary object from your FireBaseData like this.
let arrayOfDictionary = self.bookingInfo.flatMap { $0.toAnyObject() as? [String:Any] }
You will get your desired result in arrayOfDictionary it is type of [[String:Any]]