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
Related
I'm trying to pass data from a news Api to a tableView, but I'm having an issue, the data is returning nil when it get's pass to the SectorNewsVC, And by the time it gets to the infoVC it's still nil, however when I print the data before it gets pass it there. Can someone explain what I am doing wrong and, how I can go about fixing it? Thank You!!
This is where I'm creating the URLSession and fetching the data, and attempting to pass the data over to the Viewcontroller which is calling the fetchSectorNews() to retrive the data from an API.
struct FetchCategoryResponse {
let sectorUrl = "https://stocknewsapi.com/api/v1/category?section=alltickers&items=50&type=article&token=\(Key.api_key)"
func fetchSectorNews(sector: String) {
let urlString = "\(sectorUrl)§or=\(sector)"
performRequest(urlString: urlString)
print(urlString)
}
func performRequest(urlString: String) {
// create url
if let url = URL(string: urlString) {
// create url session
let session = URLSession(configuration: .default)
// give session a task
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!)
return
}
if let safeData = data {
if let news = self.parseJson(sectorData: safeData) {
DispatchQueue.main.async {
let vc = SectorNewsVC()
vc.dataToPass = news
}
}
}
}
task.resume()
}
}
// parse the jason data
func parseJson(sectorData: Data) -> SectorModel? {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(CatergoryData.self, from: sectorData)
let newsUrl = decodedData.data[1].title
let imageUrl = decodedData.data[1].news_url
let title = decodedData.data[1].title
let source = decodedData.data[1].source_name
let sectorPayload = SectorModel(url: newsUrl, image: imageUrl, title: title, source: source)
// this sectorpayload gets saved to the news var in the performrequest() bc its being return
return sectorPayload
}
catch {
print(error)
return nil
}
}
} // END Struct
so in this ViewController I'm setting up the collectionViewController and calling the fetchSectorNews() and passing in the title of the label as the argunemt for the function, while trying to pass the data over to the detialViewController
var titleArr = ["Technology", "Materials", "HealthCare"]
var dataToPass: SectorModel?
var fetchNews = FetchCategoryResponse()
extension SectorNewsVC: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return titleArr.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! SectorCollectionCell
cell.listLabel.text = titleArr[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let curentIndex = indexPath.item
if curentIndex == 0 {
fetchNews.fetchSectorNews(sector: "technology")
}
else if curentIndex == 1 {
fetchNews.fetchSectorNews(sector: "materials")
}
else if curentIndex == 2 {
fetchNews.fetchSectorNews(sector: "healthcare")
}
performSegue(withIdentifier: "segue", sender: nil)
} // end cv()
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue" {
if let indexPath = self.collectionView.indexPathsForSelectedItems {
let detailVC = segue.destination as! infoVC
detailVC.newData = dataToPass
print(indexPath)
}
}
}
}
Here is where I want to display the data
class infoVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var newData: SectorModel?
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .none
tableView.showsVerticalScrollIndicator = false
tableView.backgroundColor = #colorLiteral(red: 0.1926331222, green: 0.2233074605, blue: 0.3540094197, alpha: 1)
tableView.register(UINib(nibName: "DifferentSectorCell", bundle: nil), forCellReuseIdentifier: "cellId")
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cell.backgroundColor = UIColor.clear
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("tap")
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! DifferentSectorCell
cell.titleLabel.text = "hey"
cell.sourceLabel.text = "hello"
return cell
}
}
I would suggest a different approach. Sending the section to the child controller, and do the request on the child. Here is what has worked for me before
on the parent controller:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let curentIndex = indexPath.item
var sector = ""
if curentIndex == 0 {
sector = "technology"
}
else if curentIndex == 1 {
sector = "materials"
}
else if curentIndex == 2 {
sector = "healthcare"
}
performSegue(withIdentifier: "segue", sender: sector)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue" {
let detailVC = segue.destination as! infoVC
detailVC.sector = sender as! String
}
}
}
on the child controller:
var sector = ""
override func viewWillAppear() {
super.viewWillAppear()
fetchNews.fetchSectorNews(sector: self.sector)
}
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
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.
I want to passing data with segue in the tableViewCell,from BulletinBoadrViewController to BbDetailViewController
class BulletinBoadrViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var bulletinBoards = [BulletinBoard]()
override func viewDidLoad() {
super.viewDidLoad()
bulletinBoards = BulletinBoard.downloadAllBulletinBoard()
self.tableView.reloadData()
tableView.estimatedRowHeight = tableView.rowHeight
tableView.rowHeight = UITableViewAutomaticDimension
tableView.separatorStyle = .none
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return bulletinBoards.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! BulletinBoardTableViewCell
let bulletinBoard = bulletinBoards[indexPath.row]
cell.bulletinBoard = bulletinBoard
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "gotodetail", sender: indexPath)
print("Row \(indexPath.row)selected")
}
func prepareForSegue(segue: UIStoryboardSegue, sender: Any!) {
if segue.identifier == "gotodetail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let destVC = segue.destination as! BdDeatilViewController
let new = bulletinBoards[indexPath.row]
destVC.bulletinBoard = new
}
}
}
and it's BdDeailViewController
class BdDeatilViewController:UIViewController {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var timeLabel: UILabel!
#IBOutlet weak var contentLabel: UITextView!
#IBAction func backtobb(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
var x = [BulletinBoard]()
var bulletinBoard : BulletinBoard!{
didSet{
self.updateUI()
}
}
func updateUI() {
timeLabel.text = bulletinBoard.time
titleLabel.text = bulletinBoard.title
contentLabel.text = bulletinBoard.content
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
}
and tableViewCell's data is taking from local json file, it's BulletinBoard code
class BulletinBoard {
var title:String?
var time:String?
var content:String?
init(title:String,time:String,content:String) {
self.title = title
self.time = time
self.content = content
}
init(bulletinBoardDictionary:[String:Any]) {
self.title = bulletinBoardDictionary["title"] as? String
self.time = bulletinBoardDictionary["time"] as? String
self.content = bulletinBoardDictionary["content"] as? String
}
static func downloadAllBulletinBoard() -> [BulletinBoard] {
var bulletinBoards = [BulletinBoard]()
//get the json data from the file
let jsonFile = Bundle.main.path(forResource: "BulletinBoardData", ofType: "json")
let jsonFileURL = URL(fileURLWithPath: jsonFile!)
let jsonData = try? Data(contentsOf: jsonFileURL)
//turn the json data into foundation objects (bulletinBoards)
if let jsonDictionary = NetworkService.parseJSONFromData(jsonData) {
let bulletinBoardDictionaries = jsonDictionary["BulletinBoard"] as! [[String:Any]]
for bulletinBoardDictionary in bulletinBoardDictionaries {
let newBulletinBoard = BulletinBoard(bulletinBoardDictionary: bulletinBoardDictionary)
bulletinBoards.append(newBulletinBoard)
}
}
return bulletinBoards
}
}
Finally,it's my StoryBoard
https://i.stack.imgur.com/JcgdH.png1
Can anyone solve my problem?Thanks!
I think you should retrieve indexPath from sender in prepareForSegue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: Any!) {
if segue.identifier == "gotodetail" {
if let indexPath = sender as? IndexPath {
let destVC = segue.destination as! BdDeatilViewController
let new = bulletinBoards[indexPath.row]
destVC.bulletinBoard = new
}
}
}
and update the UI in the viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
self.updateUI()
}
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.