Value in JSON does not display in tableviewcell custom - ios

Can't display data in TableViewCell.Data reports of events, but the when you open the array "sports" display the data in cels no.The display of the title occurs and the transfer is ended...
This is my json code...
Event.swift
import UIKit
struct Event {
let match : String
let forecast : String
let data : String
let image : UIImage
var sports : [Sport]
init (match : String, forecast : String, data: String, image : UIImage, sports : [Sport]) {
self.match = match
self.forecast = forecast
self.data = data
self.image = image
self.sports = sports
}
static func eventsFromBundle ()-> [Event] {
var events = [Event] ()
guard let url = Bundle.main.url(forResource: "events", withExtension: "json") else {
return events
}
do {
let data = try Data(contentsOf: url)
guard let rootObject = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String : Any] else {
return events
}
guard let eventObjects = rootObject["events"] as? [[String: AnyObject]] else {
return events
}
for eventObject in eventObjects {
if let match = eventObject["match"] as? String,
let forecast = eventObject["forecast"] as? String,
let data = eventObject["data"] as? String,
let imageName = eventObject["image"] as? String,
let image = UIImage(named: imageName),
let sportsObject = eventObject["sports"] as? [[String : String]]{
var sports = [Sport]()
for sportObject in sportsObject {
if let nameTitle = sportObject["name"] ,
let titleName = sportObject["image"],
let titleImage = UIImage(named: titleName + ".jpg"),
let prognozLabel = sportObject["prognoz"],
let obzor = sportObject["obzor"] {
sports.append(Sport(name: nameTitle, prognoz: prognozLabel, image: titleImage, obzor: obzor, isExpanded: false))
}
}
let event = Event(match: match, forecast: forecast, data: data, image: image, sports: sports)
events.append(event)
}
}
} catch {
return events
}
return events
}
}
import UIKit
class SportViewController: BaseViewController {
var events = Event.eventsFromBundle ()
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
addSlideMenuButton()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 100
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
NotificationCenter.default.addObserver(forName: .UIContentSizeCategoryDidChange, object: .none, queue: OperationQueue.main) { [weak self] _ in
self?.tableView.reloadData()
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? SportDetailViewController,
let indexPath = tableView.indexPathForSelectedRow {
destination.selectedEvent = events[indexPath.row]
}
}
}
extension SportViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return events.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellMatch", for: indexPath) as! SportTableViewCell
let event = events[indexPath.row]
cell.matchLabel.text = event.match
cell.imageMatch.image = event.image
cell.forecastLabel.text = event.forecast
cell.dataLabel.text = event.data
cell.matchLabel.font = UIFont.preferredFont(forTextStyle: .subheadline)
cell.forecastLabel.font = UIFont.preferredFont(forTextStyle: .callout)
return cell
}
}
Her is the controller.SportDetailViewController.swift
import UIKit
class SportDetailViewController: UIViewController {
var selectedEvent : Event!
let obzorText = "Select for more info >"
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
title = selectedEvent.match
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
}
extension SportDetailViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return selectedEvent.sports.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : SportDetailTableViewCell = tableView.dequeueReusableCell(withIdentifier: "cellMatch", for: indexPath) as! SportDetailTableViewCell
let sport = selectedEvent.sports[indexPath.row]
cell.nameTitle.text = sport.name
cell.titleImage.image = sport.image
cell.prognozLabel.text = sport.prognoz
cell.selectionStyle = .none
cell.nameTitle.backgroundColor = UIColor.darkGray
cell.backgroundColor = UIColor.red
cell.obzorText.text = sport.isExpanded ? sport.obzor : obzorText
cell.obzorText.textAlignment = sport.isExpanded ? .left : .center
return cell
}
}
extension SportDetailViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let cell = tableView.cellForRow(at: indexPath) as? SportDetailTableViewCell else { return }
var sport = selectedEvent.sports[indexPath.row]
sport.isExpanded = !sport.isExpanded
selectedEvent.sports[indexPath.row] = sport
cell.obzorText.text = sport.isExpanded ? sport.obzor : obzorText
cell.obzorText.textAlignment = sport.isExpanded ? .left : .center
tableView.beginUpdates()
tableView.endUpdates()
tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}
}
all these methods have tried: tableview.datasource = self , tableview.delegate = self и reloadData().....in viewDidLoad.

Delete this init from your struct: (because struct gets free initializer)
init (match : String, forecast : String, data: String, image : UIImage, sports : [Sport]) {
self.match = match
self.forecast = forecast
self.data = data
self.image = image
self.sports = sports
}
Now, your var events won't be populated as you are calling method in class scope. So change this:
class SportViewController: BaseViewController {
var events = Event.eventsFromBundle ()
...
...
}
to
class SportViewController: BaseViewController {
var events = [Event]()
...
...
override func viewDidLoad() {
super.viewDidLoad()
addSlideMenuButton()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 100
events = Event().eventsFromBundle()
}
...
...
}
This should solve your problem.

Related

Access correct indexPath Row for user

I'm creating a messaging app where users can select who do they want to chat with by a UITableView, the problem is that obviously there needs to be a way to search for an specific user, I had already implemented a UISearchController and I can find the user which I search for. The real problem starts when I select the user with override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) method, because when I select the user, it selects wrong user because of indexPath.row.
Here is some of my code:
NewMessageController:
import UIKit
import Firebase
import FirebaseDatabase
class NewMessageController: UITableViewController, UISearchBarDelegate, UISearchResultsUpdating {
var searchController = UISearchController()
var activityIndicator = UIActivityIndicatorView(style: .large)
var aiView = UIView()
let cellId = "cellId"
var users = [User]()
var filteredUsers = [User]()
override func viewDidLoad() {
super.viewDidLoad()
initSearchController()
setUpActivityIndicator()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(didTapCancelButton))
tableView.register(UserCell.self, forCellReuseIdentifier: cellId)
startAI()
fetchUser()
}
func initSearchController() {
searchController.loadViewIfNeeded()
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.enablesReturnKeyAutomatically = false
searchController.searchBar.returnKeyType = UIReturnKeyType.done
definesPresentationContext = true
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
searchController.searchBar.scopeButtonTitles = ["All"]
searchController.searchBar.delegate = self
}
func fetchUser() {
Database.database().reference().child("users").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = User(dictionary: dictionary)
user.id = snapshot.key
// user.setValuesForKeys(dictionary)
self.users.append(user)
DispatchQueue.main.async {
self.stopAI()
self.tableView.reloadData()
}
}
}, withCancel: nil)
}
func setUpActivityIndicator() {
aiView.layer.zPosition = 0.1
aiView.backgroundColor = UIColor.gray
aiView.alpha = 0
aiView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(aiView)
aiView.centerXAnchor.constraint(equalTo: tableView.centerXAnchor).isActive = true
aiView.centerYAnchor.constraint(equalTo: tableView.centerYAnchor, constant: -60).isActive = true
aiView.heightAnchor.constraint(equalToConstant: 150).isActive = true
aiView.widthAnchor.constraint(equalToConstant: 150).isActive = true
aiView.layer.masksToBounds = true
aiView.layer.cornerRadius = 15
activityIndicator.layer.zPosition = 0.2
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(activityIndicator)
activityIndicator.centerXAnchor.constraint(equalTo: aiView.centerXAnchor).isActive = true
activityIndicator.centerYAnchor.constraint(equalTo: aiView.centerYAnchor).isActive = true
}
func startAI() {
activityIndicator.startAnimating()
aiView.alpha = 0.80
tableView.isUserInteractionEnabled = false
}
func stopAI() {
self.activityIndicator.stopAnimating()
self.tableView.isUserInteractionEnabled = true
self.aiView.alpha = 0
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
var messagesViewController: MessagesViewController?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
dismiss(animated: true) {
let selectedUser: User!
if(self.searchController.isActive)
{
selectedUser = self.filteredUsers[indexPath.row]
}
else
{
selectedUser = self.users[indexPath.row]
}
self.messagesViewController?.showChatControllerForUser(user: selectedUser)
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (searchController.isActive) {
return filteredUsers.count
}
return users.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
startAI()
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! UserCell
let thisUser: User!
if (searchController.isActive) {
thisUser = filteredUsers[indexPath.row]
} else {
thisUser = users[indexPath.row]
}
cell.nameLabel.text = "\(thisUser.firstname!) \(thisUser.surname!)"
cell.usernameLabel.text = thisUser.username
cell.profileImageView.loadImageUsingCacheWithUrlString(urlString: thisUser.userImg!)
cell.timeLabel.text = nil
stopAI()
return cell
}
func updateSearchResults(for searchController: UISearchController) {
let searchBar = searchController.searchBar
let scopeButton = searchBar.scopeButtonTitles![searchBar.selectedScopeButtonIndex]
let searchText = searchBar.text!
filterForSearchTextAndScopeButton(searchText: searchText, scopeButton: scopeButton)
}
func filterForSearchTextAndScopeButton(searchText: String, scopeButton : String = "All") {
filteredUsers = users.filter {
user in
let scopeMatch = (scopeButton == "All" || user.username!.lowercased().contains(scopeButton.lowercased()))
if(searchController.searchBar.text != "") {
let searchTextMatch = user.username!.lowercased().contains(searchText.lowercased())
return scopeMatch && searchTextMatch
} else {
return scopeMatch
}
}
tableView.reloadData()
}
}
UserModel:
import UIKit
class User: NSObject {
#objc var id: String?
#objc var firstname: String?
#objc var surname: String?
#objc var email: String?
#objc var username: String?
#objc var userImg: String?
init(dictionary: [String: AnyObject]) {
self.id = dictionary["id"] as? String
self.firstname = dictionary["firstname"] as? String
self.surname = dictionary["surname"] as? String
self.username = dictionary["username"] as? String
self.email = dictionary["email"] as? String
self.userImg = dictionary["userImg"] as? String
}
}
The function I use for showing ChatLogController:
#objc func showChatControllerForUser(user: User) {
let chatLogController = ChatLogController(collectionViewLayout: UICollectionViewFlowLayout())
chatLogController.user = user
navigationController?.pushViewController(chatLogController, animated: true)
}
change the way to detect if is search active or not like this.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
dismiss(animated: true) {
let selectedUser: User!
if(self.searchController.searchBar.text != "")
{
selectedUser = self.filteredUsers[indexPath.row]
}
else
{
selectedUser = self.users[indexPath.row]
}
self.messagesViewController?.showChatControllerForUser(user: selectedUser)
}
}
some times searchController is active but ther searhbar is "" so is not realizable way to check where is search term or not

How can I take the sum of table view cells' data in Swift?

I'm trying to add up all of the amount data and send to a different table view cell. I think I need to convert String to Double before I can do this, but I'm not sure how to do this either. Does anyone know how you can take the sum of data and present it somewhere else? I'm very new to swift and am having trouble figuring out where I need to write this code.
import Foundation
struct Income: Codable {
var name: String
var amount: String
init(name: String, amount: String) {
self.name = name
self.amount = amount
}
static let DocumentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
static let ArchiveURL = DocumentsDirectory.appendingPathComponent("incomes").appendingPathExtension("plist")
static func loadSampleIncomes() -> [Income] {
return [
Income(name: "Main Income", amount: "0"),
Income(name: "Secondary Income", amount: "0"),
Income(name: "Interest Income", amount: "0")]
}
static func saveToFile(incomes: [Income]) {
let propertyListEncoder = PropertyListEncoder()
let codedIncomes = try? propertyListEncoder.encode(incomes)
try? codedIncomes?.write(to: ArchiveURL, options: .noFileProtection)
}
static func loadFromFile() -> [Income]? {
guard let codedIncomes = try? Data(contentsOf: ArchiveURL) else { return nil }
let propertyListDecoder = PropertyListDecoder()
return try? propertyListDecoder.decode(Array<Income>.self, from: codedIncomes)
}
}
import UIKit
class IncomeTableViewController: UITableViewController {
var incomes: [Income] = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView(frame: CGRect.zero)
if let savedIncomes = Income.loadFromFile() {
incomes = savedIncomes
} else {
incomes = Income.loadSampleIncomes()
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}
// table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return incomes.count
} else {
return 0
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "incomeCell", for: indexPath) as! IncomeTableViewCell
let income = incomes[indexPath.row]
cell.update(with: income)
cell.showsReorderControl = true
return cell
}
// MARK: - Table view delegate
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return .delete
}
override func tableView(_ tableView: UITableView, commit
editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath:
IndexPath) {
if editingStyle == .delete {
incomes.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: . automatic)
Income.saveToFile(incomes: incomes)
}
}
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
let movedIncome = incomes.remove(at: fromIndexPath.row)
incomes.insert(movedIncome, at: to.row)
tableView.reloadData()
}
#IBAction func editButtonTapped(_ sender: UIBarButtonItem) {
let tableViewEditingMode = tableView.isEditing
tableView.setEditing(!tableViewEditingMode, animated: true)
}
// Navigation
#IBAction func unwindToIncomeTableView(segue:UIStoryboardSegue) {
guard segue.identifier == "saveIncomeUnwind",
let sourceViewController = segue.source as? AddEditIncomeTableViewController,
let income = sourceViewController.income else { return }
if let selectedIndexPath = tableView.indexPathForSelectedRow {
incomes[selectedIndexPath.row] = income
tableView.reloadRows(at: [selectedIndexPath],
with: .none)
} else {
let newIndexPath = IndexPath(row: incomes.count, section: 0)
incomes.append(income)
tableView.insertRows(at: [newIndexPath], with: .automatic)
}
Income.saveToFile(incomes: incomes)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "EditIncome" {
let indexPath = tableView.indexPathForSelectedRow!
let income = incomes[indexPath.row]
let navController = segue.destination as! UINavigationController
let addEditIncomeTableViewController = navController.topViewController as! AddEditIncomeTableViewController
addEditIncomeTableViewController.income = income
}
}
}
import UIKit
class AddEditIncomeTableViewController: UITableViewController {
#IBOutlet weak var saveButton: UIBarButtonItem!
#IBOutlet weak var incomeNameTextField: UITextField!
#IBOutlet weak var incomeAmountTextField: UITextField!
var income: Income?
override func viewDidLoad() {
super.viewDidLoad()
if let income = income {
incomeNameTextField.text = income.name
incomeAmountTextField.text = income.amount
}
updateSaveButtonState()
}
override func prepare(for segue: UIStoryboardSegue, sender:
Any?) {
super.prepare(for: segue, sender: sender)
guard segue.identifier == "saveIncomeUnwind" else { return }
let name = incomeNameTextField.text ?? ""
let amount = incomeAmountTextField.text ?? ""
income = Income(name: name, amount: amount)
}
func updateSaveButtonState() {
let nameText = incomeNameTextField.text ?? ""
let amountText = incomeAmountTextField.text ?? ""
saveButton.isEnabled = !nameText.isEmpty && !amountText.isEmpty
}
#IBAction func textEditingChanged(_ sender: UITextField) {
updateSaveButtonState()
}
}
this is the table view controller in which I want the new data to be presented.
import UIKit
class BudgetHomeTableViewController: UITableViewController {
var incomes: [Income] = []
var expenses: [Expense] = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView(frame: CGRect.zero)
if let savedIncomes = Income.loadFromFile() {
incomes = savedIncomes
} else {
incomes = Income.loadSampleIncomes()
}
if let savedExpenses = Expense.loadFromFile() {
expenses = savedExpenses
} else {
expenses = Expense.loadSampleExpenses()
}
}
}
This is the cell where the data will be presented specifically
import UIKit
class BugetBalanceCell: UITableViewCell {
#IBOutlet weak var budgetBalanceText: UILabel!
var incomes: [Income] = []
var expenses: [Expense] = []
override func awakeFromNib() {
super.awakeFromNib()
let incomeTotal = incomes.map({Double($0.amount) ?? 0}).reduce(0, +)
let expenseTotal = expenses.map({Double($0.amount) ?? 0}).reduce(0, +)
let balance = incomeTotal - expenseTotal
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
First define your income,expenses arrays and load data
var incomes: [Income] = []
var expenses: [Income] = []
if let savedIncomes = Income.loadFromFile() {
incomes = savedIncomes
} else {
incomes = Income.loadSampleIncomes()
}
//do the same thing for load data to expenses array
you can get your balance = incomes - expenses using
let incomeTotal = incomes.map({Double($0.amount) ?? 0}).reduce(0, +)
let expenseTotal = expenses.map({Double($0.amount) ?? 0}).reduce(0, +)
let balance = incomeTotal - expenseTotal
use this value where you want to show in next Table View conntroller
(income as NSArray).valueForKeyPath("#sum.self")

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 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

transition from collection view to table view

guys i have a problem when i want to change from uicollectionview to uitableview..
i have this storyboard, output and code in collection view like this
this is the storyboard, which is cell have identifier "cell"
(ignore the header section thou..)
and the output like
let reuseIdentifier = "Cell"
class SummaryViewController: UICollectionViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet var collectionview: UICollectionView!
var photos:NSArray?
var items = NSMutableArray()
var TableData:Array< String > = Array < String >()
var json:String = ""
var arrayOfMenu: [ImageList] = [ImageList]()
var jsonObject: [String: AnyObject] = [String: AnyObject]()
override func viewDidLoad() {
super.viewDidLoad()
self.setUpMenu()
collectionview.dataSource = self
collectionview.delegate = self
NSLog("%d", items.count)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return arrayOfMenu.count //hitung banyak data pada array
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! UICollectionViewCell
let image = UIImage(named: items.objectAtIndex(indexPath.row) as! String)
let imageView = cell.viewWithTag(100) as! UIImageView
imageView.image = image
return cell
}
func setUpMenu() //membaca json pada setiap arraynya
{
var json: JSON = JSON (data: NSData())
DataManager.getactivityDataFromFileWithSuccess{ (data) -> Void in
json = JSON(data: data)
let results = json["results"]
for (var i = 0; i < json["Activity"].count; i++) {
if let icon: AnyObject = json["Activity"][i]["icon"].string {
self.items.addObject(icon)
dispatch_async(dispatch_get_main_queue(), {self.collectionView!.reloadData()})
var menu = ImageList(image: icon as! String)
self.arrayOfMenu.append(menu)
self.TableData.append(icon as! String)
}
}
}
}
but when i change it to table view, it gets some errors, like this
here is the storyboard with "cell" identifier same as before
but the output doesn't do the same, it becomes like this
why they won't appear like before (pic no 2)
and the code like this
class SummaryUITableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
let reuseIdentifier = "Cell"
#IBOutlet var myTableView: UITableView!
var jsonObject: [String: AnyObject] = [String: AnyObject]()
var items = NSMutableArray()
var TableData:Array< String > = Array < String >()
var arrayOfMenu: [ImageList] = [ImageList]()
override func viewDidLoad() {
super.viewDidLoad()
self.myTableView.delegate = self
self.myTableView.dataSource = self
self.setUpMenu()
var curr:Array<Summarydata> = Array <Summarydata>()
var temp:Summarydata = Summarydata()
temp.bulan = "Agustus"
temp.setFood(Nutritionmenu.data)
curr.append(temp);
var data = JSONSerializer.toJson(curr)
println(data)
NSLog("%d", items.count)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: SummaryUITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell") as! SummaryUITableViewCell
var shortDate: String {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MMMM"
return dateFormatter.stringFromDate(NSDate())
}
cell.setCell(shortDate)
let image = UIImage(named: items.objectAtIndex(indexPath.row) as! String)
let imageView = cell.viewWithTag(100) as! UIImageView
imageView.image = image
return cell
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayOfMenu.count
}
func setUpMenu() //membaca json pada setiap arraynya
{
var json: JSON = JSON (data: NSData())
DataManager.getactivityDataFromFileWithSuccess{ (data) -> Void in
json = JSON(data: data)
let results = json["results"]
for (var i = 0; i < json["Activity"].count; i++) {
if let icon: AnyObject = json["Activity"][i]["icon"].string {
self.items.addObject(icon)
var menu = ImageList(image: icon as! String)
self.arrayOfMenu.append(menu)
self.TableData.append(icon as! String)
}
}
}
}
}
class SummaryUITableViewCell: UITableViewCell {
#IBOutlet weak var lblUnit: UILabel!
func setCell(lblUnit: String){
self.lblUnit.text = lblUnit
}
}
anyone can help?

Resources