Firebase with Swift 3.0 UITableView - ios

I goofed up. I upgraded to Swift 3.0 with out making a back up now my table view is not loading I know it pulling the data from Firebase but the table view is not loading. I was loading before the update but now no luck.
import UIKit
import Firebase
class ActiveCallsTableViewController: UITableViewController {
let cellId = "callCell"
var users = [User]()
var unAcceptedUsers = [User]()
var enRoute = [User]()
var onSite = [User]()
var isFiltered = Bool()
let section = ["Unaccepted", "Enroute", "Onsite"]
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(handleCancel))
tableView.register(UserCell.self, forCellReuseIdentifier: cellId)
fetchUser()
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
print("titleForHeader")
return self.section[section]
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
/// Returns the amount of minutes from another date
func fetchUser() {
print("This is fetchUser")
FIRDatabase.database().reference().child("Calls").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject]{
let user = User()
user.setValuesForKeys(dictionary)
self.users.append(user)
if user.Job_Status == "Unaccepted" {
self.isFiltered = true
self.unAcceptedUsers.append(user)
print("\(user.Name) True")
}else if user.Job_Status == "Enroute"{
self.isFiltered = false
self.enRoute.append(user)
print("\(user.Name) False")
}else{
self.onSite.append(user)
}
//print(self.user)
//DispatchQueue.main.asynchronously(execute: {self.tableView.reloadData()})
DispatchQueue.main.async (execute: { self.tableView.reloadData()
print("Later in fetchUser")
})
}
}, withCancel: nil)
}
func handleCancel() {
dismiss(animated: true, completion: nil)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//var rowCount: Int
print(" This is numbers Of Rows")
if section == 0 {
//rowCount = unAcceptedUsers.count
print(unAcceptedUsers.count)
return unAcceptedUsers.count
}
else if section == 1{
return enRoute.count
//rowCount = enRoute.count
}else {
return onSite.count
}
//return rowCount
}
func userForIndexPath(indexPath: NSIndexPath) -> User {
if indexPath.section == 0 {
// print(unAcceptedUsers)
return unAcceptedUsers[indexPath.row]
}
print(enRoute)
return unAcceptedUsers[indexPath.row]
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//print("Call Cell")
//let cell = UITableViewCell(style: .Subtitle, reuseIdentifier: cellId)
print("CellForRow")
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath as IndexPath)
let user:User
//let user = userForIndexPath(indexPath)
if indexPath.section == 0 {
user = unAcceptedUsers[indexPath.row]
}else if indexPath.section == 1{
user = enRoute[indexPath.row]
}else{
user = onSite[indexPath.row]
}
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = .short
let date3 = dateFormatter.date(from: user.Time_Logged!)
print("THE TIME IS \(date3)")
let elapesedTime = NSDate().timeIntervalSince(date3!)
//let minutesPassed = (elapesedTime / 3600)
//let dateMinutes = NSDate().timeIntervalSinceReferenceDate (date3)
// let calcendar = NSCalendar.currentCalendar()
//let dateComponents = calcendar.components(NSCalendarUnit.Minute, fromDate: date3!, toDate: NSDate(), options: nil)
//let minutesPassed = dateComponents
print ("THE TIME IS \(elapesedTime)")
let duration = Int(elapesedTime)
let minutesLogged = String(duration)
print(duration)
//let user = users[indexPath.row]
cell.textLabel?.text = user.Name
cell.detailTextLabel?.text = minutesLogged
//print(user.Adress)
return cell
}
//var valueToPass:String!
var valueToPass:String!
//var productsValue = [unAcceptedCallDataVie]]
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
let callInfoView:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "Callinfo") as UIViewController
let unAcceptedView:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "unAcceptedCall") as UIViewController
let currentCell = tableView.cellForRow(at: indexPath as IndexPath) as UITableViewCell!;
if indexPath.section == 0 {
valueToPass = currentCell?.textLabel!.text
//valueToPass = currentCell2
performSegue(withIdentifier: "passData", sender: self)
self.present(unAcceptedView, animated: true, completion: nil)
//print(valueToPass)
}else if indexPath.section == 1{
self.present(callInfoView, animated: true, completion: nil)
print("Enroute")
}else {
self.present(callInfoView, animated: true, completion: nil)
print("Onsite")
}
// print(user.Adress)
}
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "passData") {
//let user:User
// initialize new view controller and cast it as your view controller
let viewController = segue.destination as! unAcceptedCallDataView
// your new view controller should have property that will store passed value
//var passedValue = viewController.nameLable.text
//print(user.Adress)
viewController.LableText = valueToPass
}
class UserCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder){
fatalError("init(coder:) has not been implemented")
}}}}
`

Try replacing :-
DispatchQueue.main.async (execute:...
To
DispatchQueue.global(qos: .background).async {
self.tableView.reloadData()
DispatchQueue.main.async {
self.tableView.reloadData()
}
}

Related

How to pass data from UI Table View to UI Collection View inside Table View Cell?

i have ui collection view on my table view cell using xib .
i want to pass data that i get from API to ui collection view inside table view cell
this is my code
model
class MessageTextType {
var messageType: String = ""
var messageFromMe: String = ""
var date: String = ""
var type: String = ""
var text: String = ""
var image: String = ""
var imagePreview: String = ""
var time: String = ""
var speech: String = ""
var resolvequery: String = ""
var columnCarousel: String = ""
}
table view
var messageTextArray : [MessageTextType] = [MessageTextType]()
var messageFromMe : [MessageInput] = [MessageInput]()
override func viewDidLoad() {
super.viewDidLoad()
chatTableView.delegate = self
chatTableView.dataSource = self
chatMessage.delegate = self
chatTableView.register(UINib(nibName: "MessageText", bundle: nil), forCellReuseIdentifier: "MessageText")
chatTableView.register(UINib(nibName: "MessageFromMe", bundle: nil), forCellReuseIdentifier: "MessageFromMe")
chatTableView.register(UINib(nibName: "ChatImage", bundle: nil), forCellReuseIdentifier: "MessageImage")
chatTableView.register(UINib(nibName: "MessageCarousel", bundle: nil), forCellReuseIdentifier: "MessageCarousel")
configureTableView()
chatTableView.separatorStyle = .none
showNavItem()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let chatinfo = messageTextArray[indexPath.item]
if chatinfo.messageType == "chatInput" {
let cell : MessageFromMe! = tableView.dequeueReusableCell( withIdentifier: "MessageFromMe") as? MessageFromMe
cell.chatMe.text = chatinfo.messageFromMe
cell.time.text = chatinfo.time
return cell
}
else{
if chatinfo.type == "image" {
let cell : ChatImage! = tableView.dequeueReusableCell( withIdentifier: "MessageImage") as? ChatImage
let remoteImageURL = URL(string: chatinfo.image)!
Alamofire.request(remoteImageURL).responseData { (response) in
if response.error == nil {
print(response.result)
if let data = response.data {
cell.chatImage.image = UIImage(data: data)
}
}
}
return cell
}else if chatinfo.type == "text" {
let cell : MessageText! = tableView.dequeueReusableCell( withIdentifier: "MessageText") as? MessageText
cell.chatText.text = chatinfo.text
return cell
}
else {
let cell : MessageCarousel! = tableView.dequeueReusableCell( withIdentifier: "MessageCarousel") as? MessageCarousel
return cell
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messageTextArray.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func configureTableView() {
chatTableView.rowHeight = UITableView.automaticDimension
chatTableView.estimatedRowHeight = 500.0
}
#IBAction func sendPressed(_ sender: Any) {
chatInput()
getDataText()
chatMessage.text = ""
}
func chatInput() {
let messageRespon = MessageTextType()
let date = Date()
let formatter = DateFormatter()
formatter.timeStyle = .short
formatter.dateStyle = .none
messageRespon.messageType = "chatInput"
messageRespon.messageFromMe = chatMessage.text!
messageRespon.time = formatter.string(from: date)
messageTextArray.append(messageRespon)
configureTableView()
chatTableView.reloadData()
}
func getDataText() {
startAnimating(type: NVActivityIndicatorType.ballPulseSync)
let id = UserDefaults.standard.object(forKey: "id") as! String
let chatParams : [String : Any] = [ "user_id": id,
"bot_id": "dBmK5m",
"query": chatMessage.text!
]
let token = UserDefaults.standard.object(forKey: "token") as! String
let headersku: HTTPHeaders = [
"Content-Type":"application/json",
"Accept": "application/json",
"Authorization": "Bearer \(token)"
]
Alamofire.request(base_url+"/chat", method: .post, parameters: chatParams,encoding: JSONEncoding.default, headers: headersku)
.responseJSON {
response in
if response.result.isSuccess {
let loginJSON : JSON = JSON(response.result.value!)
print(loginJSON)
let output = loginJSON["result"]["output"]
for (_, subJson):(String, JSON) in output {
let text = subJson["text"].stringValue
let type = subJson["type"].stringValue
let speech = subJson["speech"].stringValue
let image = subJson["originalContentUrl"].stringValue
let date = loginJSON["timestamp"]["date"].stringValue
let resolvequery = loginJSON["resolvequery"].stringValue
let columns = subJson["columns"]
let message = MessageTextType()
message.text = text
message.messageType = "text"
message.type = type
message.speech = speech
message.image = image
message.date = date
message.resolvequery = resolvequery
self.messageTextArray.append(message)
if type == "text" {
let utterance = AVSpeechUtterance(string: output[0]["text"].stringValue +
". "+output[1]["text"].stringValue)
utterance.rate = 0.5
utterance.voice = AVSpeechSynthesisVoice(language: "id-ID")
let voice = AVSpeechSynthesizer()
voice.speak(utterance)
}
}
self.configureTableView()
self.chatTableView.reloadData()
self.stopAnimating()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.1, execute: {
let indexPath = IndexPath(row: self.messageTextArray.count-1, section: 0)
self.chatTableView.scrollToRow(at: indexPath, at: UITableView.ScrollPosition.bottom, animated: true)
})
}
else {
let alertController = UIAlertController(title: "warning", message: "server sedang bermasalah , coba lagi", preferredStyle: .alert)
let action1 = UIAlertAction(title: "Ok", style: .default) { (action:UIAlertAction) in
self.stopAnimating()
}
alertController.addAction(action1)
self.present(alertController, animated: true, completion: nil)
}
}
}
collection view inside table view cell
import UIKit
class MessageCarousel: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var carouselImage: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.carouselImage.dataSource = self
self.carouselImage.delegate = self
self.carouselImage.register(UINib.init(nibName: "CarouselViewCell", bundle: nil), forCellWithReuseIdentifier: "carouselViewID")
self.carouselImage.reloadData()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "carouselViewID", for: indexPath as IndexPath) as! CarouselViewCell
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(indexPath.row)
}
}
import UIKit
class ViewController : UIViewController {
}
extension ViewController:UITableViewDataSource,UITableViewDelegate{
// this is for your tableView
In your tableView Cell :-
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let chatinfo = messageTextArray[indexPath.item]
let cell : MessageCarousel! = tableView.dequeueReusableCell( withIdentifier: "MessageCarousel") as? MessageCarousel
if yourModelData != nil{
// reload collectionView
}
return cell
}
}
extension ViewController :UICollectionViewDataSource,UICollectionViewDelegate{
// This is for Your CollectionView
// In collection View
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if yourModelData.count != 0{
return yourModelData.count
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "carouselViewID", for: indexPath as IndexPath) as! CarouselViewCell
// handle Model here
let msg = yourModelData[indexPath.row]. messageFromMe
return cell
}
}
// hope its worked for you
you have to pass data in cellrowAt method.
update your code :
let cell : MessageCarousel! = tableView.dequeueReusableCell( withIdentifier: "MessageCarousel") as? MessageCarousel
** cell.yourDataArray = chatinfo.arrayColumns **
cell.carouselImage.reloadData()
return cel
// yourInputArray is array that contain collectionview data
class MessageCarousel: UITableViewCell {
var yourDataArray = NSMutableArray() // or any other array.
//.... your code
}
You have to update your model MessageTextType, add array of columns variable in MessageTextType
class MessageTextType {
var arrayColumns : [Column]!
//... your rest code
}
class Column {
var thumbnailImageUrl : String!
var title : String!
public class func modelsFromDictionaryArray(array:NSArray) -> [Column]
{
var models:[Column] = []
for item in array
{
models.append(Column(dictionary: item as! NSDictionary)!)
}
return models
}
required public init?(dictionary: NSDictionary) {
thumbnailImageUrl = dictionary["thumbnailImageUrl"] as? String ?? ""
title = dictionary["title"] as? String ?? ""
}
init() {
}
}
add this code in API response:
let columns = Column.modelsFromDictionaryArray(array:subJson["columns"])
message.arrayColumns = columns

How do I lock specific rows in a tableview through in-app purchases?

I have a tableview that requires users to pay in order to access its content. However, the entire tableview is locked. I would like to have, for example, the first two rows unlocked and the third row locked. I also have other tableviews with over 12 rows in them, but just posting this view controller for now. I am feeding in my data through an array, and I already have in-app purchases set up. Here is my current code:
import Foundation
import UIKit
class TrappingVC: UIViewController {
#IBOutlet weak var buildingTableView: UITableView!
#IBOutlet weak var settingsButtonItem: UIBarButtonItem!
var trapping: [CellObject] = []
var segueIdentifiers = ["a", "b"]
//VIEWDIDLOAD
override func viewDidLoad() {
super.viewDidLoad()
//LOAD ARRARYS
trapping = createBuildArray()
buildingTableView.delegate = self
buildingTableView.dataSource = self
self.buildingTableView.rowHeight = 100.0
buildingTableView.tableFooterView = UIView()
//CELL SEPARATORS
buildingTableView.layoutMargins = UIEdgeInsets.zero
buildingTableView.separatorInset = UIEdgeInsets.zero
buildingTableView.separatorColor = UIColor.black
buildingTableView.register(UINib.init(nibName: "TrappingCell", bundle: nil), forCellReuseIdentifier: "TrappingCell")
settingsButtonItem.image = UIImage(named: "Settings")
}
#IBAction func showSettingsClicked(_ sender: Any) {
performSegue(withIdentifier: "showSettings", sender: self)
}
//CREATE ARRAY OF BASIC LESSONS
func createBuildArray() -> [CellObject]{
var tempTrapping: [CellObject] = []
let trapping1 = CellObject(image: #imageLiteral(resourceName: "Yellow"), title: "Below")
let trapping2 = CellObject(image: #imageLiteral(resourceName: "Yellow"), title: "Side")
let trapping3 = CellObject(image: #imageLiteral(resourceName: "Yellow"), title: "Above")
tempTrapping.append(trapping1)
tempTrapping.append(trapping2)
tempTrapping.append(trapping3)
return tempTrapping
}
}
//TABLE
extension TrappingVC: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return trapping.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let trappings = trapping[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "TrappingCell") as! TrappingCell
cell.trappingTitle.text = trappings.title
cell.trappingImage.image = trappings.image
if let purchased = UserDefaults.standard.value(forKey: "payment") as? Bool{
if purchased == true{
cell.lockedImage.isHidden = true
}else{
cell.lockedImage.isHidden = false
}
}else{
cell.lockedImage.isHidden = false
}
cell.layoutIfNeeded()
cell.layoutMargins = UIEdgeInsets.zero
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let purchased = UserDefaults.standard.value(forKey: "payment") as? Bool{
if purchased == true{
performSegue(withIdentifier: segueIdentifiers[indexPath.row], sender: self)
}else{
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "UnlockContentVC")
self.navigationController?.pushViewController(controller, animated: true)
}
}else{
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "UnlockContentVC")
self.navigationController?.pushViewController(controller, animated: true)
}
tableView.deselectRow(at: indexPath, animated: true)
}
}
I fixed it with the following code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let purchased = UserDefaults.standard.value(forKey: "payment") as? Bool
if indexPath.row < 5 {
performSegue(withIdentifier: segueIdentifiers[indexPath.row], sender: self)
}
else if purchased == true {
performSegue(withIdentifier: segueIdentifiers[indexPath.row], sender: self)
} else {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "UnlockContentVC")
self.navigationController?.pushViewController(controller, animated: true)
}
tableView.deselectRow(at: indexPath, animated: true)
}

How can I retrieve a property value from child array object?

I'm trying to call an object property from a child array. In the viewcontroller the categories and subcategories are loaded with name, path and images. A new class created for sub-categories able to get name and path but can't retreive the image. The Parent categories are returning all the info including icons however the sub-categories not able to get the image.
ViewController.swift segue prepare.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier! == "catalogproduct") {
let viewController:CatalogProduct = segue.destination as UIViewController as! CatalogProduct
viewController.productImageUrl = self.imageUrl
viewController.productId = self.productId
viewController.productName = self.productName
viewController.productPrice = ""
}
if (segue.identifier! == "productcategory") {
let viewController:Productcategory = segue.destination as UIViewController as! Productcategory
viewController.categoryId = categoryId
viewController.categoryName = categoryName;
viewController.categoryType = categoryType;
}else if (segue.identifier! == "search") {
let viewController:SearchSuggestion = segue.destination as UIViewController as! SearchSuggestion
viewController.isHome = true;
}else if (segue.identifier == "subcategory") {
let viewController:subCategory = segue.destination as UIViewController as! subCategory
viewController.subName = categoryName
viewController.subId = categoryId
viewController.subCategoryData = subCategory
}
}
The category section getting all info
import UIKit
class CategoriesController: UIViewController,UITableViewDelegate, UITableViewDataSource {
var cataegoriesCollectionModel = [Categories]()
#IBOutlet weak var categoriesTableView: UITableView!
var arrayForBool :NSMutableArray = [];
var categoryName:String = ""
var categoryId:String = ""
var categoryDict :NSDictionary = [:]
var subCategory:NSArray = []
var subId:String = ""
var subName:String = ""
override func viewDidLoad() {
super.viewDidLoad()
//self.navigationItem.title = NetworkManager.sharedInstance.language(key: "Categories")
let image = UIImage(named: "logo.png")
navigationItem.titleView = UIImageView(image: image)
let paymentViewNavigationController = self.tabBarController?.viewControllers?[0]
let nav1 = paymentViewNavigationController as! UINavigationController;
let paymentMethodViewController = nav1.viewControllers[0] as! ViewController
cataegoriesCollectionModel = paymentMethodViewController.homeViewModel.cataegoriesCollectionModel
categoriesTableView.register(UINib(nibName: "CategoriesTableViewCell", bundle: nil), forCellReuseIdentifier: "cell")
self.categoriesTableView.separatorStyle = .none
categoriesTableView.delegate = self;
categoriesTableView.dataSource = self;
categoriesTableView.separatorColor = UIColor.clear
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat{
return 0
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return SCREEN_WIDTH / 2;
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cell.backgroundColor = UIColor.white
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cataegoriesCollectionModel.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
categoriesTableView.register(UINib(nibName: "CategoryCellTableViewCell", bundle: nil), forCellReuseIdentifier: "CategoryCellTableViewCell")
let cell:CategoriesTableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell") as! CategoriesTableViewCell
cell.backgroundImageView.image = UIImage(named: "ic_placeholder.png")
NetworkManager.sharedInstance.getImageFromUrl(imageUrl:cataegoriesCollectionModel[indexPath.row].thumbnail , imageView: cell.backgroundImageView)
cell.categoryName.text = cataegoriesCollectionModel[indexPath.row].name
cell.selectionStyle = .none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let childrenArray = cataegoriesCollectionModel[indexPath.row].children! as NSArray;
if childrenArray.count > 0{
subId = cataegoriesCollectionModel[indexPath.row].id
subName = cataegoriesCollectionModel[indexPath.row].name
subCategory = childrenArray
self.performSegue(withIdentifier: "subcategory", sender: self)
}
else{
categoryId = cataegoriesCollectionModel[indexPath.row].id
categoryName = cataegoriesCollectionModel[indexPath.row].name
self.performSegue(withIdentifier: "productCategorySegue", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "productCategorySegue") {
let viewController:Productcategory = segue.destination as UIViewController as! Productcategory
viewController.categoryType = ""
viewController.categoryName = self.categoryName
viewController.categoryId = self.categoryId
}else if (segue.identifier == "subcategory") {
let viewController:subCategory = segue.destination as UIViewController as! subCategory
viewController.subName = subName
viewController.subId = subId
viewController.subCategoryData = subCategory
}
}
}
Subcategory class:
import UIKit
class subCategory: UIViewController,UITableViewDelegate, UICollectionViewDelegate, UICollectionViewDataSource {
var cataegoriesCollectionModel = [Categories]()
public var subCategoryData :NSArray = []
public var categoryName = " "
var subCategoryMenuData:NSMutableArray = []
var categoryId:String = " ";
var subId:String = ""
var subName:String = ""
#IBOutlet weak var subCategoryTable: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = NetworkManager.sharedInstance.language(key: "Categories")
self.navigationController!.isNavigationBarHidden = false
subCategoryTable.backgroundColor = UIColor().HexToColor(hexString: GREYBLACK)
let paymentViewNavigationController = self.tabBarController?.viewControllers?[0]
let nav1 = paymentViewNavigationController as! UINavigationController;
let paymentMethodViewController = nav1.viewControllers[0] as! ViewController
cataegoriesCollectionModel = paymentMethodViewController.homeViewModel.cataegoriesCollectionModel
let childArray : NSArray? = subCategoryData
if let itemsArray = childArray{
for (item) in itemsArray{
let childStoreData:NSDictionary = item as! NSDictionary;
self.subCategoryMenuData.add(childStoreData["name"] as? String! ?? "empty");
}
}
subCategoryTable.register(UINib(nibName: "subCategoryCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "listcollectionview")
subCategoryTable.delegate = self
subCategoryTable.dataSource = self
print(subCategoryData)
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ view: UICollectionView, heightForHeaderInSection section: Int) -> CGFloat{
return 0
}
func collectionView(_ view: UICollectionView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return SCREEN_WIDTH / 4;
}
func collectionView(_ view: UICollectionView, willDisplay cell: UICollectionView, forRowAt indexPath: IndexPath) {
cell.backgroundColor = UIColor.white
}
func collectionView(_ view: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return subCategoryMenuData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
subCategoryTable.register(UINib(nibName: "subCategoryCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "listcollectionview")
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "listcollectionview", for: indexPath) as! subCategoryCollectionViewCell
cell.backgroundImageView.image = UIImage(named: "ic_placeholder.png")
NetworkManager.sharedInstance.getImageFromUrl(imageUrl:cataegoriesCollectionModel[indexPath.row].thumbnail , imageView: cell.backgroundImageView)
cell.categoryName.text = (subCategoryMenuData [indexPath.row] as? String)
cell.categoryName?.textColor = UIColor().HexToColor(hexString: REDCOLOR)
return cell;
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let childDict: NSDictionary = subCategoryData .object(at: indexPath.row) as! NSDictionary
if (childDict.object(forKey: "children") as! NSArray).count > 0{
let sb = UIStoryboard(name: "Main", bundle: nil)
let initViewController: subCategory? = (sb.instantiateViewController(withIdentifier: "subCategory") as? subCategory)
initViewController?.subCategoryData = (childDict.object(forKey: "children") as! NSArray)
initViewController?.subName = childDict.object(forKey: "name") as! String!
initViewController?.subId = childDict.object(forKey: "path") as! String!
initViewController?.modalTransitionStyle = .flipHorizontal
self.navigationController?.pushViewController(initViewController!, animated: true)
}else{
categoryName = childDict .object(forKey: "name") as! String
categoryId = childDict .object(forKey: "path") as! String
self.performSegue(withIdentifier: "productCategorySegue", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "productCategorySegue") {
let viewController:Productcategory = segue.destination as UIViewController as! Productcategory
viewController.categoryType = ""
viewController.categoryName = self.categoryName
viewController.categoryId = self.categoryId
}
}
override func viewWillAppear(_ animated: Bool) {
self.navigationItem.title = categoryName;
self.navigationController!.isNavigationBarHidden = false
}
}
The JSON response printed:
categories = (
{
children = (
{
children = (
{
children = (
);
column = 1;
icon = "https://example.com/image/cache/placeholder-150x150_0.png";
image = "https://example.com/image/categories/1.jpg";
name = "Subcat Name";
path = 1197;
thumb = "https://example.com/image/categories/1.jpg";
},
How to retrieve the image for subcategory?
A quick solution would be to pass the image url string "https://example.com/image/categories/1.jpg" into a function that returns an image:
Synchronously
func imageFromURL(_ urlStr: String) -> UIImage? {
guard
let url = URL(string: urlStr),
let data = try? Data(contentsOfUrl:url),
let image = UIImage(data: data)
else {return nil}
return image
}
aSynchronously
extension UIImageView {
func loadImageFrom(urlString: String, mode: UIViewContentMode) {
guard let url = URL(string: urlString) else {return}
self.contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
error == nil,
let httpURLResponse = response as? HTTPURLResponse,
httpURLResponse.statusCode == 200,
let data = data,
let image = UIImage(data: data)
else {
return print(error?.localizedDescription ?? "Something went wrong when loading the image")
}
DispatchQueue.main.async {
self.image = image
}
}
.resume()
}
}
Use
imageView.loadImageFrom(urlString:"https://example.com/image/categories/1.jpg", mode: .scaleAspectFit)
-
See link for more details:
Loading Image From URL

Cannot invoke "index" with an argument list of type'(of: ChecklistItem)' [duplicate]

This question already has answers here:
Cannot invoke 'indexOf' with an argument list of type '(ChecklistItem)'
(5 answers)
Closed 5 years ago.
I don't understand Xcode is returning this error when I have put item in an array, and set the variables for the ChecklistItem object. I have commented the line which is returning the error.
import UIKit
class ChecklistViewController: UITableViewController, AddItemViewControllerDelegate {
var items: [ChecklistItem]
required init?(coder aDecoder: NSCoder) {
items = [ChecklistItem]()
let row0item = ChecklistItem()
row0item.text = "Walk the dog"
row0item.checked = false
items.append(row0item)
let row1item = ChecklistItem()
row1item.text = "Brush my teeth"
row1item.checked = true
items.append(row1item)
let row2item = ChecklistItem()
row2item.text = "Learn iOS development"
row2item.checked = true
items.append(row2item)
let row3item = ChecklistItem()
row3item.text = "Soccer practice"
row3item.checked = false
items.append(row3item)
let row4item = ChecklistItem()
row4item.text = "Eat ice cream"
row4item.checked = true
items.append(row4item)
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ChecklistItem", for: indexPath)
let item = items[indexPath.row]
let label = cell.viewWithTag(1000) as! UILabel
label.text = item.text
configureText(for: cell, with: item)
configureCheckmark(for: cell, with: item)
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
let item = items[indexPath.row]
item.toggleChecked()
item.checked = !item.checked
configureCheckmark(for: cell, with: item)
}
tableView.deselectRow(at:indexPath, animated: true)
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
items.remove(at: indexPath.row)
let indexPaths = [indexPath]
tableView.deleteRows(at: indexPaths, with: .automatic)
}
func configureCheckmark(for cell: UITableViewCell, with item: ChecklistItem) {
let label = cell.viewWithTag(1001) as! UILabel
if item.checked {
label.text = "√"
} else {
label.text = " "
}
}
func configureText(for cell: UITableViewCell, with item: ChecklistItem) {
let label = cell.viewWithTag(1000) as! UILabel
label.text = item.text
}
func addItemViewControllerDidCancel(_ controller: AddItemViewController) {
dismiss(animated: true, completion: nil)
}
func addItemViewController(_ controller: AddItemViewController, didFinishAdding item: ChecklistItem) {
let newRowIndex = items.count
items.append(item)
let indexPath = IndexPath(row: newRowIndex, section: 0)
let indexPaths = [indexPath]
tableView.insertRows(at: indexPaths, with: .automatic)
dismiss(animated: true, completion: nil)
}
func addItemViewController(_ controller: AddItemViewController, didFinishEditing item: ChecklistItem) {
if let index = items.index(of: item) { // Cannot invoke "index" with an argument list of type'(of: ChecklistItem)'
let indexPath = IndexPath(row: index, section: 0)
if let cell = tableView.cellForRow(at: indexPath) {
configureText(for: cell, with: item)
}
}
dismiss(animated: true, completion: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "AddItem" {
let navigationController = segue.destination as! UINavigationController
let controller = navigationController.topViewController as! AddItemViewController
controller.delegate = self
} else if segue.identifier == "EditItem" {
let navigationController = segue.destination as! UINavigationController
let controller = navigationController.topViewController as! AddItemViewController
controller.delegate = self
if let indexPath = tableView.indexPath(for: sender as! UITableViewCell) {
controller.itemToEdit = items[indexPath.row]
}
}
}
}
ChecklistItem.swift
import Foundation
class ChecklistItem {
var text = ""
var checked = false
func toggleChecked() {
checked = !checked
}
}
You need to conform to Equatable protocol..
Any maybe google beforehand.

Duplicated messages Using JSQMessagerViewController (Swift) (iOS)

I have a JSQMessagersViewController which is connected to a NavigationController. Moreover, I have a ViewController with a tableView with the contacts. Thus, when you click on a cell from the tableView, it opens the JSQMessagerViewController with that conversation. Inside the conversation, when the user sends a message the first time everything works fine. However, once the user goes out the conversation to the tableViewController, if he gets back in a conversation and sends a message, the message gets duplicated by the number of time the user when out and back in. In addition, once the message is duplicated and the user goes out of the conversation, once he click on the same conversation, the message is no longer duplicated. Indeed, when I verify on the database (Firebase), there is no duplicated messages. I can't figure out what is creating this loop.
MessageReceivedDelegate.swift
import Foundation
import Firebase
protocol MessageReceivedDelegate: class {
func message_received(senderID: String, senderName: String, text: String, target: String)
}
class messages_help {
private static let _instance = messages_help()
weak var delegate: MessageReceivedDelegate?
private var currentTarget = String()
static var Instance: messages_help {
return _instance
}
func sendMessage(senderID: String, senderName: String, text: String, target: String) {
let ref = FIRDatabase.database().reference(fromURL: )
let data: Dictionary <String, Any> = [Constants.sender_id: senderID, Constants.sender_name: senderName, Constants.text: text, Constants.target: target]
ref.child("messages").childByAutoId().setValue(data)
}
func getData() {
let ref = FIRDatabase.database().reference(fromURL: )
let user = FIRAuth.auth()?.currentUser
let curr = ref.child("messages")
curr.observe(.childAdded, with: {(snapshot) in
//print(snapshot)
//Get Value from DataBase
print()
if let data = snapshot.value as? NSDictionary {
if let senderID = data[Constants.sender_id] as? String{
if let senderName = data[Constants.sender_name] as? String {
if let target = data[Constants.target] as? String{
if user?.uid == senderID || user?.email == target{
if let text = data[Constants.text] as? String {
self.delegate?.message_received(senderID: senderID, senderName: senderName, text: text, target: target)
}
}
}
}
}
}
},withCancel: nil)
}
}
}
ChatViewController.swift
import UIKit
import JSQMessagesViewController
import MobileCoreServices
import AVKit
import FirebaseAuth
class ChatViewController: JSQMessagesViewController,
MessageReceivedDelegate {
#IBOutlet var targetLabel: UINavigationItem!
var messages = [JSQMessage]()
#IBOutlet var chatLabel: UINavigationItem!
var i = 0
var targetEmail = String()
override func viewDidLoad() {
super.viewDidLoad()
let user = FIRAuth.auth()?.currentUser
messages_help.Instance.delegate = self
self.senderId = user?.uid
self.senderDisplayName = user?.email
self.targetLabel.title = targetEmail
setupBackButton()
// Show Button to simulate incoming messages
self.inputToolbar.contentView.leftBarButtonItem = nil
if Language().check_language() == "Fr"{
self.inputToolbar.contentView.textView.placeHolder = "Nouveau message";
}
else if Language().check_language() == "Es"{
self.inputToolbar.contentView.textView.placeHolder = "Nuevo mensaje";
}
self.inputToolbar.contentView.rightBarButtonItem.setImage(UIImage(named: "paper_plane"), for: .normal)
self.inputToolbar.contentView.rightBarButtonItem.setTitleColor(UIColor.brown, for: .normal)
automaticallyScrollsToMostRecentMessage = true
//self.collectionView?.reloadData()
//messages_help.Instance.getData()
// Do any additional setup after loading the view.
messages.removeAll()
messages_help.Instance.getData()
}
func go() {
let toViewController = storyboard?.instantiateViewController(withIdentifier: "previous") as! PreviousRequestsViewController
//Go to the page
self.present(toViewController, animated:true, completion: nil)
}
//message received
func message_received(senderID: String, senderName: String, text: String, target: String) {
if target == targetEmail || senderName == targetEmail {
//print("Number of loop\n")
//i = i+1
// print(i)
/**
* Scroll to actually view the indicator
*/
self.scrollToBottom(animated: true)
messages.append(JSQMessage(senderId: senderID, displayName: senderName, text: text))
}
collectionView.reloadData()
}
// Number of rows
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return messages.count
}
// Cell
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = super.collectionView(collectionView, cellForItemAt: indexPath) as! JSQMessagesCollectionViewCell
return cell
}
// Display messages
override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageDataForItemAt indexPath: IndexPath!) -> JSQMessageData! {
return messages[indexPath.item]
}
// Avatar
override func collectionView(_ collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAt indexPath: IndexPath!) -> JSQMessageAvatarImageDataSource! {
return JSQMessagesAvatarImageFactory.avatarImage(with: UIImage(named: "iTunesArtwork"), diameter: 30)
}
//the bubble
override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageBubbleImageDataForItemAt indexPath: IndexPath!) -> JSQMessageBubbleImageDataSource! {
let bubble_fact = JSQMessagesBubbleImageFactory()
let message = messages[indexPath.item]
if message.senderId == self.senderId {
return bubble_fact?.outgoingMessagesBubbleImage(with: UIColor.brown)
}
else {
return bubble_fact?.incomingMessagesBubbleImage(with: UIColor.darkGray)
}
}
// When pressed sent
override func didPressSend(_ button: UIButton!, withMessageText text: String!, senderId: String!, senderDisplayName: String!, date: Date!) {
messages_help.Instance.sendMessage(senderID: senderId, senderName: senderDisplayName, text: text, target: self.targetEmail )
//dismiss text from text fild
finishSendingMessage()
}
func setupBackButton() {
if Language().check_language() == "Fr"{
let backButton = UIBarButtonItem(title: "Retour", style: UIBarButtonItemStyle.plain, target: self, action: #selector(backButtonTapped))
backButton.tintColor = UIColor.brown
navigationItem.leftBarButtonItem = backButton
}
else if Language().check_language() == "Es"{
let backButton = UIBarButtonItem(title: "Regresa", style: UIBarButtonItemStyle.plain, target: self, action: #selector(backButtonTapped))
backButton.tintColor = UIColor.brown
navigationItem.leftBarButtonItem = backButton
} else {
let backButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.plain, target: self, action: #selector(backButtonTapped))
backButton.tintColor = UIColor.brown
navigationItem.leftBarButtonItem = backButton
}
}
func backButtonTapped() {
self.dismiss(animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
}
ContactChatViewController.swift
import UIKit
import Firebase
class ContactChatViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
#IBOutlet var chat_TableView: UITableView!
var ref: FIRDatabaseReference!
var publish = [String?]()
var data_to_send = String()
var encountered = Set<String>()
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference(fromURL: )
getDataa()
}
// get data from trips
func getDataa() {
// Reference to current user
let user = FIRAuth.auth()?.currentUser
let curr = ref.child("messages")
curr.observe(.childAdded, with: {(snapshot) in
if let data = snapshot.value as? [String: AnyObject] {
let use = messages()
use.setValuesForKeys(data)
//Append new data if same user
if user?.email == use.target || user?.email == use.sender_name {
if self.encountered.contains(use.sender_name!) || (user?.email)! == use.sender_name! {
//print("Already inside")
} else {
self.encountered.insert(use.sender_name!)
self.publish.append(use.sender_name)
}
//Appen to to array even if current user sent a message but is not the target
if user?.email == use.sender_name{
if self.encountered.contains(use.target!) {
print("Already inside")
} else {
self.encountered.insert(use.target!)
self.publish.append(use.target)
}
}
}
//Load data in U Thread
DispatchQueue.main.async {
self.chat_TableView.reloadData()
}
}
}
,withCancel: nil)
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
// hide separators
tableView.separatorStyle = .none
//return count with database
return publish.count
}
// Assign rows a value
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell_user = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "previous_cell")
cell_user.selectionStyle = .none
cell_user.backgroundColor = UIColor.clear
cell_user.textLabel?.textColor = UIColor.brown
cell_user.textLabel?.font = UIFont.systemFont(ofSize: 25)
// Check for duplicates
cell_user.textLabel?.text = self.publish[indexPath.row]
return cell_user
}
//Clicked on a cell
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
data_to_send = self.publish[indexPath.row]!
self.performSegue(withIdentifier: "chatSegue", sender: self)
//let chatView = ChatViewController()
//chatView.targetEmail = self.publish[indexPath.row]!
//let chatNavigationController = UINavigationController(rootViewController: chatView)
//present(chatNavigationController, animated: true, completion: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//let toViewController = storyboard?.instantiateViewController(withIdentifier: "chatPage") as! ChatViewController
//toViewController.targetEmail = data_to_send
//Go to the page
//self.present(toViewController, animated:true, completion: nil)
let navVC = segue.destination as? UINavigationController
let chatVC = navVC?.viewControllers.first as! ChatViewController
chatVC.targetEmail = data_to_send
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}

Resources