Why my Data model aren't upload in my tableviewcontroller - swift

I don't know why I can't view my pets in the table.
Few days ago the app is working perfect but when I updated the last version of Xcode the app crashed, I can't see the data whet the App run.
I new developer in swift
Help me, please.
------------------------------Model------------------------
import UIKit
struct InfoPet{
let PetPicture: String
let PetBackground: String
let PetName: String
let PetAge: String
static func InfoPets() -> [InfoPet]{
let pet1 = InfoPet(PetPicture: "Drako", PetBackground: "Background Can", PetName: "Drako", PetAge: "2 years old")
let pet2 = InfoPet(PetPicture: "Lucky", PetBackground: "Background Cat", PetName: "Lucky", PetAge: "3 years old")
return [pet1, pet2]
}
}
-----------------------TableViewController----------------
class PetsTableViewController: UITableViewController {
// MARK: - Global Var
var pets: [InfoPet] = InfoPet.InfoPets()
// MARK: - UITableViewDataSource
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pets.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PetCell", for: indexPath) as! PetsTableViewCell
let pet = pets[indexPath.row]
cell.pet = pet
return cell
}
// MARK: - UITableViewDalegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}
-----------------------tableViewCell-----------------------
class PetsTableViewCell: UITableViewCell {
#IBOutlet weak var ImgPhotoPet: UIImageView!
#IBOutlet weak var ImgBackgroundPet: UIImageView!
#IBOutlet weak var LblNamePet: UILabel!
#IBOutlet weak var LblAgePet: UILabel!
var pet: InfoPet!{
didSet{
updateUI()
}
}
func updateUI() {
ImgBackgroundPet.image = UIImage(named: pet.PetBackground)
ImgPhotoPet.image = UIImage(named: pet.PetPicture)
ImgPhotoPet.layer.cornerRadius = 10.0
ImgPhotoPet.layer.masksToBounds = true
LblNamePet.text = pet.PetName
LblAgePet.text = pet.PetAge
}
}

Add Cell Identifier as "PetCell"
and add viewDidLoad method in PetsTableViewController class.
create IBOutlet of the table view.
#IBOutlet weak var tableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableview.dataSource = self
tableview.delegate = self
}

Related

Label.text Error! - Unexpectedly found nil while implicitly unwrapping an Optional value

I am new to iOS development and I found an error that I can not get past. I have read a lot online and on Stackoverflow but I don't understand why this error keeps coming up.
Upon testing and doing breakpoints I think I was able to get the data needed problem is when I display it on screen wit uilabel.
import UIKit
class ArtistViewController: UIViewController, artistViewModelDelegate {
#IBOutlet weak var artwork: UIImageView!
#IBOutlet weak var artistName: UILabel!
#IBOutlet weak var albumName: UILabel!
func loadArtistViewModel(data: ArtistViewModel) {
guard let artistData = data as? ArtistViewModel else {}
artistName.text = artistData.artistName //Unexpectedly found nil while unwrapping an Optional value
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Hope you guys can help me on this one, Thank you so much!
EDIT
ViewController where the instance of ArtistViewController gets called
import UIKit
import Alamofire
import SwiftyJSON
protocol artistViewModelDelegate {
func loadArtistViewModel(data: ArtistViewModel)
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, artistSearchDelegate {
#IBOutlet weak var tableView: UITableView!
var data: [ArtistItem] = []
var delegate: artistViewModelDelegate?
var artistViewModel: ArtistViewModel?
var params = [API_CONSTANTS.URL_TYPES.PARAMETERS.TERM: "Maroon 5",API_CONSTANTS.URL_TYPES.PARAMETERS.COUNTRY: API_CONSTANTS.AU, API_CONSTANTS.URL_TYPES.PARAMETERS.MEDIA: API_CONSTANTS.URL_TYPES.PARAMETERS.MUSIC]
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = ArtistViewController()
getItunesData()
tableView.dataSource = self
tableView.delegate = self
tableView.register(UINib(nibName: "artistCell", bundle: nil), forCellReuseIdentifier: "artistCell")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "artistCell", for: indexPath) as! artistCell
cell.artistName.text = data[indexPath.row].artistName
cell.albumName.text = data[indexPath.row].albumName
cell.genre.text = data[indexPath.row].genre
cell.trackPrice.text = "$\(String(data[indexPath.row].trackPrice))"
cell.albumArtwork.load(url: data[indexPath.row].artwork)
cell.layer.cornerRadius = 5
cell.layer.masksToBounds = true
return cell
}
//Mark: To Artist ViewController
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
artistViewModel = ArtistViewModel(artist: data[indexPath.row])
let artistViewController = storyboard?.instantiateViewController(withIdentifier: "ArtistViewController") as! ArtistViewController
delegate?.loadArtistViewModel(data: artistViewModel!)
self.navigationController?.pushViewController(artistViewController, animated: true)
}
func getItunesData(){
Alamofire.request(API_CONSTANTS.URL_TYPES.URL, method: .get, parameters: params).responseJSON
{ response in
if response.result.isSuccess {
let json = JSON(response.result.value)
self.data = ArtistModel(json: json).artistItems
self.tableView.reloadData()
} else {
}
}
}
func didTapSearch(artist: String) {
params = [API_CONSTANTS.URL_TYPES.PARAMETERS.TERM:"\(artist)"]
getItunesData()
}
#IBAction func searchButton(_ sender: Any) {
let popupSearchVC = storyboard?.instantiateViewController(withIdentifier: "popupSearchView") as! PopupViewController
popupSearchVC.delegate = self
present(popupSearchVC, animated: true, completion: nil)
}
}
The problem is the protocol. You set delegate to an instance which is not the instance in the storyboard.
But with the given code you don't need the protocol at all.
Delete
protocol artistViewModelDelegate {
func loadArtistViewModel(data: ArtistViewModel)
}
...
var delegate: artistViewModelDelegate?
...
self.delegate = ArtistViewController()
and the protocol conformance, then replace
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
artistViewModel = ArtistViewModel(artist: data[indexPath.row])
let artistViewController = storyboard?.instantiateViewController(withIdentifier: "ArtistViewController") as! ArtistViewController
delegate?.loadArtistViewModel(data: artistViewModel!)
self.navigationController?.pushViewController(artistViewController, animated: true)
}
with
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let artistViewController = storyboard?.instantiateViewController(withIdentifier: "ArtistViewController") as! ArtistViewController
artistViewController.artistViewModel = ArtistViewModel(artist: data[indexPath.row])
self.navigationController?.pushViewController(artistViewController, animated: true)
}
And in ArtistViewController you have to use a temporary variable for the model because the outlets are not connected (yet) right after instantiation.
Replace the code in the question with
import UIKit
class ArtistViewController: UIViewController, artistViewModelDelegate {
#IBOutlet weak var artwork: UIImageView!
#IBOutlet weak var artistName: UILabel!
#IBOutlet weak var albumName: UILabel!
var artistViewModel : ArtistViewModel!
override func viewDidLoad() {
super.viewDidLoad()
artistName.text = artistViewModel.artistName
}
}

in the Table view I want to add some images but when I run it doesn't show and I already import the images in assets.xcassets

I already make an array to access the picture.. Can someone help? thanks
Here is my code:
import UIKit
class MainMenuViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let labeltitle = ["Acme De la Vie Tee", "Anti Social Social Club Black Hoodie", "CDG Play Gold Black Tee"]
let labelprice = [("RM 240"), ("RM 305"), ("RM 418")]
let myImage = [UIImage(named: "adlv1"), UIImage(named: "assc"), UIImage(named: "cdg1")]
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return labeltitle.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MainMenuTableViewCell
cell.label11?.text = labeltitle[indexPath.row]
cell.label2?.text = labelprice[indexPath.row]
cell.myImage.image = self.myImage[indexPath.row]
return cell
}
}
Here is my code for MainMenuTableViewCell
import UIKit
class MainMenuTableViewCell: UITableViewCell {
#IBOutlet weak var label11: UILabel!
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var myImage: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
you need to register your tableviewcell in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.register(MainMenuTableViewCell.self, forCellReuseIdentifier: "cell")
}
Apple Documentation
More Info
Did u add constraint ?
Select to viewController and do reset the suggested constraint and im sure it will be solved
cell.myImage.image = self.myImage[indexPath.row]
try to change your image Array name

Second Level UITableView not working in SWIFT

I've got a UITableView like so:
import UIKit
import SDWebImage
class ChatViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var ConversationList: UITableView!
let apiService = APIService()
var conversations: [Conversation] = []
var selectedConversation: Int?
override func viewDidLoad() {
super.viewDidLoad()
ConversationList.separatorStyle = .none
ConversationList.dataSource = self
ConversationList.delegate = self
// load Conversations
self.apiService.getConversations(completion: {result in
switch result {
case .success(let conversations):
DispatchQueue.main.async {
print("NUMBER OF CONVERSATIONS: ", conversations.count)
self.conversations = conversations
self.ConversationList.reloadData()
}
case .failure(let error):
print("An error occured \(error.localizedDescription)")
}
})
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.conversations.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ChatViewCell", for: indexPath) as! ChatViewCellController
cell.UserName.text = self.conversations[indexPath[1]].participants![1].username
let imgURL = URL(string: self.conversations[indexPath[1]].participants![1].profileimage!)
cell.UserLogo.sd_setImage(with: imgURL, placeholderImage: UIImage(named: "icon.turq.png"))
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("selected row number ", indexPath)
self.selectedConversation = indexPath[1]
self.performSegue(withIdentifier: "ChatToChatDetail", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destination = segue.destination as! ChatDetailViewController
destination.name = self.conversations[self.selectedConversation!].participants![1].username!
destination.img = self.conversations[self.selectedConversation!].participants![1].profileimage!
}
}
The UITableViewCell sits in a separate, simple class like so:
import UIKit
class ChatViewCellController: UITableViewCell {
#IBOutlet weak var UserLogo: UIImageView!
#IBOutlet weak var UserName: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
self.UserLogo.clipsToBounds = true
self.UserLogo.layer.cornerRadius = self.UserLogo.frame.size.width / 2
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
As shown above, selecting a specific cell (i.e conversation) in the UITableView loads another UIViewController via segue. That UIViewController then contains another UITableView:
import UIKit
import SDWebImage
class ChatDetailViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var UserLogo: UIImageView!
#IBOutlet weak var UserName: UILabel!
#IBOutlet weak var MessageList: UITableView!
var name: String = ""
var img: String = ""
let apiService = APIService()
var messages: [ChatMessage] = []
override func viewDidLoad() {
super.viewDidLoad()
// prepare header section:
self.MessageList.separatorStyle = .none
let imgURL = URL(string: self.img)
self.UserLogo.sd_setImage(with: imgURL, placeholderImage: UIImage(named: "icon.turq.png"))
self.UserLogo.clipsToBounds = true
self.UserLogo.layer.cornerRadius = self.UserLogo.frame.size.width / 2
self.UserName.text = self.name
// TODO: load messages
self.MessageList.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MessageViewCell", for: indexPath) as! ChatMessageViewCellController
cell.ChatMessageText.text = "foo"
return cell
}
}
The UITableViewCell for the above UITableView is again sitting in a separate, simple class:
import UIKit
class ChatMessageViewCellController: UITableViewCell {
#IBOutlet weak var ChatMessageBubble: UIView!
#IBOutlet weak var ChatMessageText: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
print("I'm awake")
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Everything works fine up until a certain point. The first Table View loads and shows all Chats. Clicking on a Chat loads the new View with the header section, showing the Logo and Name of the Chat partner at the top of the screen and a Table underneath it. However, that table does not contain anything. To my understanding, with this code, it should show 10 rows saying "foo" and print 10 times "I'm awake" to the console.
What am I missing or doing wrong here?
In your second ViewController, you are not setting UITableViewDelegate and UITableViewDataSource. What you need to add to viewDidLoad:
MessageList.delegate = self
MessageList.dataSource = self
Bonus, for future change self.selectedConversation = indexPath[1] in first view controller to prevent bug - it will always take second model, even if you have only one.
Also, try to avoid upper case for attributes, e.g. MessageList -> messageList.

Object is not setup correctly when passing it across classes

I'm having trouble pushing new ViewController in swift.
class CartViewController: UITableViewController {
static var items:[Item] = []
override func viewDidLoad() {
super.viewDidLoad()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return CartViewController.items.count
}
//if cell is selected
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = storyboard?.instantiateViewController(withIdentifier: "PaymentController") as! PaymentController
print(CartViewController.items[indexPath.row].title)
vc.item? = CartViewController.items[indexPath.row]
self.navigationController?.pushViewController(vc, animated: true)
}
The print function up there gives the right result, but there's nothing showing up when the new vc is pushed. debugger shows the
vc.item
is nil.
This is what I have in PaymentController class
class PaymentController: UIViewController {
#IBOutlet weak var myImage: UIImageView?
#IBOutlet weak var myTitle: UILabel?
#IBOutlet weak var myPrice: UILabel?
var item:Item?
override func viewDidLoad() {
super.viewDidLoad()
myImage?.image = UIImage(named: item!.image)
myTitle?.text = item!.title
myPrice?.text = String(item!.price)
}
}
Any hints or ideas will be appreciated:))
In tableView(_,didSelectRowAt:) try removing the ? in line 3.
I.e., replace vc.item? = (...) with vc.item = (...)

ViewController does not conform to protocol 'UITableViewDataSource

**Where's the wrong?
ERROR "SecondViewController does not conform to protocol 'UITableViewDataSource"**
import UIKit
class SecondViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
{
#IBOutlet weak var tableView: UITableView!
var videos:[video] = [video]()
#IBOutlet weak var menuButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
let model = videoModel()
self.videos = videoModel().getVideos()
self.tableView.dataSource = self
self.tableView.delegate = self
}
func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return videos.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "BasicCell", for: indexPath)
let videoTitle = videos[indexPath.row].videoTitle
//customize the cell
cell.textLabel?.text = videoTitle
return cell
}
}
}
Perhaps, You did not connect UIViewController and UITableView.
In Stroyboard,
Place your mouse over UITableView, Drag to UIViewController using right button. And then you can check outlets options, datasource and delegate. Check these.