can't reload Array<any>? data from firebase to Table View swift - arrays

my Data Model :
class KeyModell {
var UserID : String?
var key : Array<Any>?
init(UserIDString : String , keyString : Array<Any>? ) {
UserID = UserIDString
key = keyString
}
}
My ViewContoller :
class ViewController: UIViewController {
var userID = ""
var keyContiner = [KeyModell]()
#IBOutlet weak var tableViewOutLet: UITableView!
#IBOutlet weak var textFeildOUtLet: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
FetchUsers(userID: userID) { (user) in
// print("userID His Profile \(user.id)")
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
fetchKey()
tableViewOutLet.reloadData()
}
#objc func fetchKey () {
Database.database().reference().child("AdminKeys").observeSingleEvent(of: .value) { (snapshot) in
// print(snapshot.value)
for child in snapshot.children.allObjects as! [DataSnapshot] {
if let dict = child.value as? [String : Any] {
// print(dict)
let userID = dict["UserID"] as! String
if let keyID = dict["key"] as! Array<Any>? {
let key = KeyModell.init(UserIDString: userID, keyString: keyID)
self.keyContiner.append(key)
self.tableViewOutLet.reloadData()
}
self.tableViewOutLet.reloadData()
}
}
}
func FetchUsers (userID : String , Compation : #escaping (UserModel)->Void) {
Database.database().reference().child("Users").child(userID).observe(.childAdded) { (snapshot) in
if let dic = snapshot.value as? [String : Any] {
let user = UserModel.TransferUserModel(dic: dic, key: snapshot.key)
Compation(user)
}
}
}
#IBAction func saveKeybtn(_ sender: Any) {
let keyString : String = textFeildOUtLet.text!
let keys = keyString.components(separatedBy: ",")
let ref : DatabaseReference!
ref = Database.database().reference()
let AdminKeysREF = ref.child("AdminKeys")
let newKeysPostID = AdminKeysREF.childByAutoId()
guard let userID = Auth.auth().currentUser else {return}
let userKeyId = userID.uid
newKeysPostID.setValue(["UserID": userKeyId , "key" : keys] )
}
extension ViewController : UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return keyContiner.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! KeyCell
return cell
}
My Cell :
class KeyCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
#IBOutlet weak var keyOUtLet: UILabel!
var key : KeyModell?{
didSet {
upDatekey()
}
}
func upDatekey() {
keyOUtLet.text = key?.key
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
My database :
when i print(cell.key) it give me result :
the problem was when i try to set lable to key mode like this :
func upDatekey() {
keyOUtLet.text = key?.key
}
it give me error "Cannot assign value of type '[Any]?' to type 'String?'"
as my database key value are Array so i set it like this :
var key : Array<Any>?
i think the problem from here i can't figuer it out

I solve the issue ,
my firebase database node is an Int array , so i have to cast my object as [String] than i loop thrught the arrya to extract the kyes
if let key = dict["key"] as? [String] {
for keys in key {
print(keys)
}
than i load it to table view . it work fine .

Related

How Create Global Array and save Values in Two TableViews in Swift

Here i am creating Global array and appending values to it, which i need to save in two different viewcontrollers tableview
Global array and appending values and sending to two view controllers code:
var addressArray = [String]()
class NewZoomAddressViewController: UIViewController {
weak var delegate: DataEnteredDelegate? = nil
//var addressArray = [String]()
var zipName: String?
var localityName: String?
var sublocalityName: String?
var streetNumber: String?
var streetName: String?
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var addressLabel: UILabel!
var viewController: UIViewController?
#IBAction func confirmBtn(_ sender: Any) {
for controller in navigationController?.viewControllers ?? [] {
if let listController = controller as? ProfileViewController {
let string = "\(streetNumber ?? "") \(streetName ?? "") \(sublocalityName ?? "") \(zipName ?? "") \(localityName ?? "")"
saveaddAddressService()
listController.addressArray.append(string)
navigationController?.popToViewController(controller, animated: true)
return
}
else if let listController = controller as? Add_EditAddressViewController {
let string = "\(sublocalityName ?? "") \(zipName ?? "") \(localityName ?? "")"
listController.addressArray.append(string)
saveaddAddressService()
navigationController?.popToViewController(controller, animated: true)
return
}
}
}
func saveaddAddressService(){
let parameters: [String: Any] = [
"pincode": zipName,
"city": localityName,
"streetName": sublocalityName,
"colony": "",
]
//some JSON code.....
let httpResponse = response as? HTTPURLResponse
if httpResponse!.statusCode == 200 {
do {
let jsonObject = try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as! [String: Any]
self.addAddrsID = jsonObject["addressId"] as! String
UserDefaults.standard.set(self.addAddrsID, forKey: "addAddress")
} catch { print(error.localizedDescription) }
}
})
dataTask.resume()
}
Saving array in first view controller view controllers: here i am getting each time with new address the model address also coming, i dont know why?
class ProfileViewController: UIViewController {
var userModel : ProfileModel?
var addressArray = [String]()
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.navigationBar.isHidden=true
getUserProfile()
}
func getUserProfile() {
let httpResponse = response as? HTTPURLResponse
if httpResponse!.statusCode == 200 {
do {
let jsonObject = try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as! [String :AnyObject]
self.userModel = ProfileModel.init(fromDictionary: jsonObject)
if (self.userModel?.userId) != nil {
DispatchQueue.main.async {
self.updateUserDetails()
self.addressTableview.reloadData()
}
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if userModel?.userAddresses != nil{
return userModel?.userAddresses.count ?? 0
}
else{
return addressArray.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: AddresCell = tableView.dequeueReusableCell(withIdentifier: "AddresCell") as! AddresCell
let addr = userModel?.userAddresses![indexPath.row]
if addr?.addressId != nil{
let street = addr?.streetName
let colony = addr?.colony
let city = addr?.city
let pincode = addr?.pincode
cell.address.text = street! + "," + colony! + "," + city! + "," + pincode!
}
else{
cell.address.text = addressArray[indexPath.row]
print("added address in profilr \(cell.address.text)")
}
return cell
}
saving global array in second view controller: here array values are coming, but if i go from this view controller to other view controller the array values gone(not coming.. showing empty.. not saving)
class Add_EditAddressViewController: UIViewController,DataEnteredDelegate {
#IBOutlet weak var addeditTableview: UITableView!
var addressArray = [String]()
override func viewWillAppear(_ animated: Bool) {
addeditTableview.reloadData()
}
}
extension Add_EditAddressViewController : UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return addressArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "EditAddressTableViewCell", for: indexPath) as! EditAddressTableViewCell
cell.editButton.addTarget(self, action: #selector(editbuttonClicked(sender:)), for: .touchUpInside)
cell.nameHeader.text = "Other"
cell.addressLabel.text = addressArray[indexPath.row]//"\(city) \(pincode) \(locality)"
}
return cell
}
you can create a singleton class to manage your global array like below GlobalArrayManager class:
import Foundation
class GlobalArrayManager{
static let shared = GlobalArrayManager()
var globalArray : [Int] = []
private init(){}
func getArray()->[Int]{
return globalArray
}
func addDataInArray(data : Int){
globalArray.append(data)
}
}
In first ViewController add data and print:
GlobalArrayManager.shared.addDataInArray(data: 100)
print("array values : ",GlobalArrayManager.shared.getArray())
Output In first ViewController:
array values : [100]
In second ViewController add data and print:
GlobalArrayManager.shared.addDataInArray(data: 200)
print("array values : ",GlobalArrayManager.shared.getArray())
Output In Second ViewController:
array values : [100, 200]
you can add more functionalities in your manager class

Swift - Tableview not updating properly with search queries

I'm using the search bar controller with a tableview. I'm fetching the contacts on my phone to populate the tableview. Here's my code for this part.
func fetchContacts(){
let key = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey] as [CNKeyDescriptor]
let request = CNContactFetchRequest(keysToFetch: key)
try! contactStore.enumerateContacts(with: request) {(contact, stoppingPointer) in
let name = "\(contact.givenName) \(contact.familyName)"
let number = contact.phoneNumbers.first?.value.stringValue
for numbero in contact.phoneNumbers {
if let number = numbero.value as? CNPhoneNumber,
let label = numbero.label {
var contactToAppend = ContractStruct(givenName: name, number: number.stringValue)
self.contacts.append(contactToAppend)
}
}
}
tableView.reloadData()
}
It retrieves the contact with different phone numbers properly and then displays in the tableview. I've also added multi selection on the tableview to be able to select multiple contacts to continue with my flow of the app.
My issue is when I'm searching for the contact in the search bar , it always gives me the wrong contacts in my tableview. It comes up with the same name always at the top. Returns wrong contact
Now if I print my filteredcontact list , it returns the proper contact that should have been displayed but it is not displayed on the tableview. Here's my code for the search
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text! == "" {
filteredContacts = contacts
} else {
// Filter the results
filteredContacts = contacts.filter { $0.givenName.lowercased().contains(searchBar.text!.lowercased())
}
}
print(filteredContacts)
tableView.reloadData()
}
And here's my full class:
class ContactsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
var contactStore = CNContactStore()
var contacts = [ContractStruct]()
var filteredContacts = [ContractStruct]()
var setSelectedItems: Set<Int> = []
var searching = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tableView.delegate = self
tableView.dataSource = self
searchBar.delegate = self
contactStore.requestAccess(for: .contacts) {(success, error) in
if success {
print("Authorisation Successful")
}
self.fetchContacts()
}
filteredContacts = contacts
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredContacts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: nil)
if setSelectedItems.contains(indexPath.row) {
cell.accessoryType = .checkmark
}
else {
cell.accessoryType = .none
}
let contactToDisplay = contacts[indexPath.row]
cell.textLabel?.text = contactToDisplay.givenName
cell.detailTextLabel?.text = contactToDisplay.number
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if setSelectedItems.contains(indexPath.row) {
setSelectedItems.remove(indexPath.row)
} else {
setSelectedItems.insert(indexPath.row)
}
tableView.reloadRows(at: [indexPath], with: .none)
print(setSelectedItems)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text! == "" {
filteredContacts = contacts
} else {
// Filter the results
filteredContacts = contacts.filter { $0.givenName.lowercased().contains(searchBar.text!.lowercased())
}
}
print(filteredContacts)
tableView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searching = false
searchBar.text = ""
tableView.reloadData()
}
func fetchContacts(){
let key = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey] as [CNKeyDescriptor]
let request = CNContactFetchRequest(keysToFetch: key)
try! contactStore.enumerateContacts(with: request) {(contact, stoppingPointer) in
let name = "\(contact.givenName) \(contact.familyName)"
let number = contact.phoneNumbers.first?.value.stringValue
for numbero in contact.phoneNumbers {
if let number = numbero.value as? CNPhoneNumber,
let label = numbero.label {
var contactToAppend = ContractStruct(givenName: name, number: number.stringValue)
self.contacts.append(contactToAppend)
}
}
}
tableView.reloadData()
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
Just replace contacts[indexPath.row] to filteredContacts[indexPath.row] in cellForRowAt function of tableView delegate.
Because your filtered results stored in filteredContacts and your tableView delegate functions use filteredContacts
I had to replace filteredContacts[indexPath.row] in cellForRowAt for it to work.

How to compare and display different array count in numberOfRowsInSection in tableview in swift

I have tableview with label, i need to display different array count in tableview for different category. for that i have taken different arrays for different category but i am unable to check condition, all the time the condition goes to outer return count in numberOfRowsInSection and i am getting all category values in tableview.
I have to compare homeVC typeName with AllMakePaymentViewController category name and display accordingly in tableview.
HomeVC code for saving and selecting type for displaying category values in AllMakePaymentViewController tableview:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if itemsArray[indexPath.item].typeName == "WATER"{
let nextViewController = self.storyboard?.instantiateViewController(withIdentifier: "AllMakePaymentViewController") as? AllMakePaymentViewController
self.navigationController?.pushViewController(nextViewController!, animated: true)
}
else if itemsArray[indexPath.item].typeName == "ELECTRICITY"{
let nextViewController = self.storyboard?.instantiateViewController(withIdentifier: "AllMakePaymentViewController") as? AllMakePaymentViewController
self.navigationController?.pushViewController(nextViewController!, animated: true)
}
else if itemsArray[indexPath.item].typeName == "CASH POINT"{
let nextViewController = self.storyboard?.instantiateViewController(withIdentifier: "AllMakePaymentViewController") as? AllMakePaymentViewController
self.navigationController?.pushViewController(nextViewController!, animated: true)
}
else{
AlertFun.ShowAlert(title: "", message: "will update soon..", in: self)
}
}
//MARK:- Service-call
func homeServiceCall(){
do{
let jsonObj = try JSONSerialization.jsonObject(with: respData, options: .allowFragments) as! [String: Any]
//print("the home json is \(jsonObj)")
let financerArray = jsonObj["financer"] as! [[String: Any]]
for financer in financerArray {
let id = financer["id"] as? String
let pic = financer["icon"] as? String
self.typeName = financer["tpe"] as! String
KeychainWrapper.standard.set(self.typeName!, forKey: "typeName")
var saveTypenameKey = KeychainWrapper.standard.string(forKey: "typeName")
print("keychain typename \(KeychainWrapper.standard.set(self.typeName!, forKey: "typeName"))")
self.itemsArray.append(JsonData(icon: pic ?? "", tpe: self.typeName ?? "", id: id ?? ""))
}
}
catch {
print("catch error")
}
}).resume()
}
AllMakePaymentViewController code:
import UIKit
class PaymentTableViewCell: UITableViewCell{
#IBOutlet weak var pamntTypeLabel: UILabel!
}
class AllMakePaymentViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var electricityArray = [String]()
var waterArray = [String]()
var iteamsArray = [String]()
var categoryName: String?
override func viewDidLoad() {
super.viewDidLoad()
allPaymentService()
}
func allPaymentService(){
let urlStr = "https://dev.com/webservices/api.php?rquest=billermdm"
let url = URL(string: urlStr)
URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in
guard let respData = data else {
return
}
guard error == nil else {
print("error")
return
}
do{
let jsonObj = try JSONSerialization.jsonObject(with: respData, options: .allowFragments) as! [String: Any]
//print("the all make payment json is \(jsonObj)")
let billerdetailsArray = jsonObj["billerdetails"] as! [[String: Any]]
for billerdetail in billerdetailsArray {
self.categoryName = billerdetail["bcategoryname"] as? String
if self.categoryName == "Water"{
let bName = billerdetail["bname"] as? String
self.waterArray.append(bName ?? "")
}
if self.categoryName == "cashpoint"{
let bName = billerdetail["bname"] as? String
self.iteamsArray.append(bName ?? "")
}
if self.categoryName == "Electricity"{
let bName = billerdetail["bname"] as? String
self.electricityArray.append(bName ?? "")
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
catch {
print("catch error")
}
}).resume()
}
}
extension AllMakePaymentViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if categoryName == "Water"{
return waterArray.count
}
if categoryName == "cashpoint"{
return iteamsArray.count
}
if categoryName == "Electricity"{
return electricityArray.count
}
return iteamsArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! PaymentTableViewCell
if categoryName == "Electricity"{
cell.pamntTypeLabel.text = electricityArray[indexPath.row]
}
if categoryName == "Water"{
cell.pamntTypeLabel.text = waterArray[indexPath.row]
}
if categoryName == "cashpoint"{
cell.pamntTypeLabel.text = iteamsArray[indexPath.row]
}
else
{
cell.pamntTypeLabel.text = iteamsArray[indexPath.row]
}
self.tableView.separatorStyle = .none
return cell
}
}
How to compare homeVC typeName select from didselectItematIndex with AllMakePaymentViewController categoryname and show only selected item categoryName values in tableview label. please help me in the above code. I got stuck here from long time.
You need top inject the category into the nextViewControllers so it knows what data to display. To minimise the use of string literals, I'm converting them into an enum, and have changed the code to use this instead.
enum Category: String {
case water = "WATER"
case electricity = "ELECTRICITY"
case cashpoint = "CASHPOINT"
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let nextViewController = self.storyboard?.instantiateViewController(withIdentifier: "AllMakePaymentViewController") as? AllMakePaymentViewController
switch Category(rawValue: [indexPath.item].typeName) {
case .water: nextViewcontroller.category = .water
case .electricity: nextViewcontroller.category = .electricity
case .cashpoint: nextViewcontroller.category = .cashpoint
default: AlertFun.ShowAlert(title: "", message: "will update soon..", in: self)
}
self.navigationController?.pushViewController(nextViewController!, animated: true)
}
class AllMakePaymentViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var electricityArray = [String]()
var waterArray = [String]()
var iteamsArray = [String]()
var category: Category?
//load data etc
}
extension AllMakePaymentViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let category = category else {return 0}
switch category {
case .electricity: return electricityArray.count
case .water: return waterArray.count
case .cashpoint: return iteamsArray.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! PaymentTableViewCell
guard let category = category else {return 0}
switch category {
case .electricity: cell.pamntTypeLabel.text = electricityArray[indexPath.row]
case .water: cell.pamntTypeLabel.text = waterArray[indexPath.row]
case .cashpoint: cell.pamntTypeLabel.text = iteamsArray[indexPath.row]
}
self.tableView.separatorStyle = .none
return cell
}
}
Note: not been able to compile this so might be small typos, but it should give you the basis for what you need. Ask if XCode throws up any syntax errors.

UICollectionView in UITableView - I want to show data in CollectionVewCell

I want to show data in UICollectionView. Which is coming from UITableView cell. My main concern is this. I am passing a key catgID from cellForRowAt in another API and getting data from it. But data is not coming proper way.
I am passing catgID from cellForRowAt and getting in another API which will show the list of data for UICollectionViewCells. Now data is coming but not in proper way.
This is my UITableView class for tableview index.
import UIKit
import Reachability
import Alamofire
var arrayMenuProducts = [structMenuProducts]()
struct structMenuProducts {
var id:Int
var product_name:String
var category:String
var product_image:String
var price:String
var unit_price:Double
var addons:NSArray
}
class MenuVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
var reachability = Reachability()!
#IBOutlet weak var tableview: UITableView!
var arrayMenuCat = [structMenuCat]()
struct structMenuCat{
var id:Int
var category_name:String
}
override func viewDidLoad() {
super.viewDidLoad()
menuVegAPI()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayMenuCat.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
catgID = arrayMenuCat[indexPath.row].id
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1") as! MenuTableCell
cell.lblCategoryTitle.text = arrayMenuCat[indexPath.row].category_name
cell.collectionviewOne.reloadData()
// let catid = arrayMenuCat[indexPath.row].id
// print(catid)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 216
}
func menuVegAPI()
{
if (reachability.connection == .wifi) || (reachability.connection == .cellular)
{
arrayMenuCat.removeAll()
SwiftLoader.show(animated: true)
let url = BaseUrl + ViewController.sharedInstance.menuCategory
print(url)
Alamofire.request(url, method: .get, parameters: nil, encoding: URLEncoding.default).responseJSON { response in
SwiftLoader.hide()
switch response.result {
case .success:
let json = response.result.value
print(json)
let code = (json as AnyObject).object(forKey: "code") as! Int
print(code)
if code == 200
{
let data = (json as AnyObject).object(forKey: "data") as? NSArray
for alldata in data!
{
let id = (alldata as AnyObject).object(forKey: "id") as! Int
let category_name = (alldata as AnyObject).object(forKey: "category_name") as! String
let arr = structMenuCat(id: id, category_name: category_name)
self.arrayMenuCat.append(arr)
// self.menuProductsAPI(categoryid: id)
}
self.tableview.reloadData()
}
else
{
}
case .failure:
print("error")
}
}
}
else
{
alert(title: "", message: "Please Check Your Internet Connection")
}
}
}
This is my TableViewCell type class. In this class I am show data on CollectionView. Its code is here
import UIKit
import Alamofire
import Reachability
var catgID : Int!
var collectionreload : UICollectionView?
class MenuTableCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate {
var reachability = Reachability()!
#IBOutlet weak var lblCategoryTitle: UILabel!
#IBOutlet weak var collectionviewOne: UICollectionView!
var arrayMenuProducts = [structMenuProducts]()
struct structMenuProducts {
var id:Int
var product_name:String
var category:String
var product_image:String
var price:String
var unit_price:Double
var addons:NSArray
}
override func awakeFromNib() {
super.awakeFromNib()
collectionreload = self.collectionviewOne
print(arrayMenuProducts)
print(catgID ?? 0)
menuProductsAPI(categoryid: catgID!)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return arrayMenuProducts.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CellRID", for: indexPath) as! MenuCollectionViewCell
let abc = arrayMenuProducts[indexPath.row].product_name
print(abc)
// if catgID == Int(arrayMenuProducts[indexPath.row].category)
// {
cell.lblTitleForVeg.text = arrayMenuProducts[indexPath.row].product_name
cell.lblForPriceVeg.text = "$\(arrayMenuProducts[indexPath.row].unit_price)"
}
func menuProductsAPI(categoryid:Int)
{
if (reachability.connection == .wifi) || (reachability.connection == .cellular)
{
SwiftLoader.show(animated: true)
arrayMenuProducts.removeAll()
let url = BaseUrl + ViewController.sharedInstance.menuProducts + "categoryid=\(categoryid)"
print(url)
Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default).responseJSON { response in
switch response.result {
case .success:
let json = response.result.value
print(json)
// self.tableview.reloadData()
let code = (json as AnyObject).object(forKey: "code") as! Int
print(code)
if code == 200
{
let data = (json as AnyObject).object(forKey: "data") as? NSArray
DispatchQueue.main.async {
for alldata in data!
{
let id = (alldata as AnyObject).object(forKey: "id") as! Int
let product_name = (alldata as AnyObject).object(forKey: "product_name") as! String
let category = (alldata as AnyObject).object(forKey: "category") as! String
let product_image = (alldata as AnyObject).object(forKey: "product_image") as! String
let price = (alldata as AnyObject).object(forKey: "price") as! String
let unit_price = (alldata as AnyObject).object(forKey: "unit_price") as! Double
let addons = (alldata as AnyObject).object(forKey: "addons") as? NSArray
let arr = structMenuProducts(id: id, product_name: product_name, category: category, product_image: product_image, price: price, unit_price: unit_price, addons: addons!)
self.arrayMenuProducts.append(arr)
}
self.collectionviewOne.reloadData()
SwiftLoader.hide()
}
}
else
{
}
case .failure:
print("error")
}
}
}
else
{
// alert(title: "", message: "Please Check Your Internet Connection")
}
}
}
I want to show data coming in CollectionView in a proper formate. If Tableview index == 0 and Category id is coming 10 then. Category id 10 will first then one by one in a sequence I want to pass category id. In my case Category id is not coming in a queue.
Update the tableview datasource method as
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1") as! MenuTableCell
cell.lblCategoryTitle.text = arrayMenuCat[indexPath.row].category_name
cell.menuProductsAPI(categoryid: arrayMenuCat[indexPath.row].id)
return cell
}
And remove menuProductsAPI(categoryid: catgID!) from awakeFromNib method

Cannot assign value of type '[[String : AnyObject]]' to type '[[String : AnyObject?]]'

I'm getting the following error:
Cannot assign value of type '[[String : AnyObject]]' to type '[[String : AnyObject?]]'
It's strange this assignment was working before then when I restarted my Xcode, I started to get this error. From what I have read online, this should not give the error.
Here is my code:
import UIKit
import Alamofire
import SwiftyJSON
class Signal Condo TableViewController: UITableViewController {
#IBOutlet var tableview: UITableView!
var singleCondoData = [[String:AnyObject]]()
var CondoIndivi = [[String:AnyObject]]()
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
self.tableView.delegate = self
self.tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return singleCondoData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! SignleTableTableViewCell
if singleCondoData.count != 0 {
let dict = singleCondoData[indexPath.row] as NSDictionary
//cell.label1.text? = (dict["name"] as? String)!
if let nullcheck = (dict["address"] as? String) {
cell.label2.text? = nullcheck
}
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let dict = singleCondoData[indexPath.row] as NSDictionary
if let unitNullCheck = (dict["mls_number"] as? String) {
let item_id = unitNullCheck
getCondoUnits(item_id)
print(item_id)
}
}
//get the individual condo id
func getCondoUnits(condo_id : String){
Alamofire.request(.GET, "http://android.goidx.com/search/?mls_number=" + String(condo_id)).validate().responseJSON { response in
if let value = response.result.value {
let json = JSON(value)
if let resData = json.arrayObject {
self.CondoIndivi = (resData as? [[String:AnyObject]])!
print(self.CondoIndivi)
}
if self.CondoIndivi.count > 0 {
self.tableview.reloadData()
}
}
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let identifier = segue.identifier {
switch identifier {
case "details" :
let buildingdDetailVC = segue.destinationViewController as! DetailsViewController
buildingdDetailVC.CondoIndivi2 = self.CondoIndivi // line of the error
default:
break
}
}
}
}
The type of CondoIndivi2 variable is [[String: AnyObject?]] but you are passing an array of type [[String: AnyObject]] where the dictionary values are non-optional.
Since any non-optional value with same type can be safely converted to its optional corresponding, you can do the following:
buildingdDetailVC.CondoIndivi2 = self.CondoIndivi.map { $0 as [String: AnyObject?] }

Resources