How to reload TableVIew Using Model NSObject Class with MVVM - ios

I want to reload TableView without tableview.reloadData() method for that i have used MVVM structure so i have attach model class to storyboard and the issue is that my tableview is reload first and then i get all data how should i solved this issue please help me if any one have a solution !!
This is storyboard model attach
Model Code :-
class MovieModel: Decodable{
var artistName: String = ""
var trackName: String = ""
init(artistName: String, trackName: String){
self.artistName = artistName
self.trackName = trackName
}
}
class ResultModel: Decodable{
var results = [MovieModel]()
init(results: [MovieModel]) {
self.results = results
}
}
My ViewModel File code :-
class MovieViewModel: NSObject {
var artistName: String = ""
var trackName: String = ""
var movieModel: MovieModel?
var movieData = [MovieViewModel]()
override init() {
}
init(movie: MovieModel) {
self.artistName = movie.artistName
self.trackName = movie.trackName
}
func getData(){
Service.shareInstance.getAllMovieData { (movie, error) in
if error == nil{
self.movieData = movie?.map({return MovieViewModel(movie: $0)}) ?? []
print(self.movieData)
}else{
print("\(String(describing: error))")
}
}
}
func numberOfRow(section:Int) -> Int{
return movieData.count
}
func cellForRow(indexPath: IndexPath) -> MovieViewModel{
return self.movieData[indexPath.row]
}
}
My ViewController Code :-
class ViewController: UIViewController {
#IBOutlet var movieVM: MovieViewModel?
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.movieVM?.getData()
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return movieVM?.numberOfRow(section: section) ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
let movie = movieVM?.cellForRow(indexPath: indexPath)
cell?.textLabel?.text = movie?.artistName
cell?.detailTextLabel?.text = movie?.trackName
return cell!
}
}
In my case i am not reload tableview all this is done using ModelClass ! Thank You !!

Related

How to get the name list on Realm database and display on my stimulator?

Here I have a Realm Database which is have some data in it and I want to display it on my Stimulator but it turn out display some other thing. What's wrong in my code?
This is the data of my Realm Database and I also marked the data which I want to display it.
The stimulator which display something like this.
And here is my ViewController.swift code's.
import UIKit
import RealmSwift
class ViewController: UIViewController,UITableViewDataSource { //UITableViewDataSource
#IBOutlet weak var mytableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let realm = try! Realm()
let theItem = realm.objects(Item.self).filter("itemid >= 1")
return theItem.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let realm = try! Realm()
let theItem = realm.objects(Item.self).filter("itemid >= 1")
print(theItem)
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1")
//I suspect the problem is at here...
cell?.textLabel?.text = "\(theItem)"
return cell!
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
}
class Category: Object {
#objc dynamic var name: String?
#objc dynamic var caid: Int = 0
}
class Item: Object {
#objc dynamic var name: String?
#objc dynamic var itemid: Int = 0
#objc dynamic var cateid: Int = 0
}
Your problem is that you need to get the string from the Item object. try something like
"\(theItem.name)".
func getNames() -> [String]{
let items = realm.objects(Item.self).filter("itemid >= 1").toArray(ofType: Item.self ) as [Item]
return items.map { $0.name }
}
extension Results {
func toArray<T>(ofType: T.Type) -> [T] {
var array = [T]()
for i in 0 ..< count {
if let result = self[i] as? T {
array.append(result)
}
}
return array
}
}
I found a way to display the data already. I just need to add indexPath.row in my code and it can handle the data already.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let realm = try! Realm()
let theItem = realm.objects(Item.self).filter("itemid >= 1")
//I only add below this indexpath
let cellData = theItem[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1")
//and change this part and it's done.
cell?.textLabel?.text = cellData.name
print(theItem)
return cell!
}

DidSelectRowAt won't return desired item

I have dynamic table which displays a number of MKMapItems - these items are being displayed by cellForRowAt. But somehow if I click on the cell didSelectRow won't return the map item if I want to print it:
class SearchResultTableViewController: UIViewController {
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var visualEffectView: UIVisualEffectView!
private enum SegueID: String {
case showDetail
case showAll
}
private enum CellReuseID: String {
case resultCell
}
private var places: [MKMapItem]? {
didSet {
tableView.reloadData()
}
}
private var suggestionController: SuggestionsTableTableViewController!
var searchController: UISearchController!
private var localSearch: MKLocalSearch? {
willSet {
places = nil
localSearch?.cancel()
}
}
private var boundingRegion: MKCoordinateRegion?
override func awakeFromNib() {
super.awakeFromNib()
...
}
override func viewDidLoad() {
super.viewDidLoad()
...
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if #available(iOS 10, *) {
visualEffectView.layer.cornerRadius = 9.0
visualEffectView.clipsToBounds = true
}
}
...
}
extension SearchResultTableViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return places?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: CellReuseID.resultCell.rawValue, for: indexPath)
if let mapItem = places?[indexPath.row] {
cell.textLabel?.text = mapItem.name
cell.detailTextLabel?.text = mapItem.placemark.formattedAddress
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
print(indexPath)
...
guard let mapItem = places?[indexPath.row] else { return }
print(mapItem.name)
...
if tableView == suggestionController.tableView, let suggestion = suggestionController.completerResults?[indexPath.row] {
searchController.isActive = false
searchController.searchBar.text = suggestion.title
search(for: suggestion)
}
}
}
guard let mapItem = places?[indexPath.row] else { return }
- are you sure this guard statement isn't returning?
also, I'm not seeing where you're setting the VC as the tableView delegate/datasource.

Firebase import array data to tableview

I have tableview in VC and I would like to import "Detail" item form current recipe:
Firebase entries
to tableView - each to a separate cell.
My Code in RecipiesModel:
class RecipiesModel {
var title: String?
var desc: String?
var detail: Array<Any>?
init(title: String?, desc: String?, detail: Array<Any>?){
self.title = title
self.desc = desc
self.detail = detail
}
}
My Code in VC:
import UIKit
import FirebaseDatabase
class DescriptionViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var textInput: String = ""
var descInput: String = ""
var ref:DatabaseReference!
var recipiesList = [RecipiesModel]()
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var titleLabelDesc: UILabel!
#IBOutlet weak var descriptionLabelDesc: UILabel!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var tabBarView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
UIApplication.shared.statusBarStyle = .lightContent
tableView.delegate = self
tableView.dataSource = self
customUIView()
titleLabelDesc.text = textInput
descriptionLabelDesc.text = descInput
loadList()
}
//Database
func loadList() {
ref = Database.database().reference()
ref.child("Recipies").observe(.childAdded, with: { (snapshot) in
let results = snapshot.value as? [String : AnyObject]
let title = results?["Recipies title"]
let desc = results?["Recipies description"]
let detail = results?["Detail"]
let myRecipies = RecipiesModel(title: title as! String?, desc: desc as! String?, detail: detail as! Array<Any>?)
self.recipiesList.append(myRecipies)
DispatchQueue.main.async {
self.tableView.reloadData()
}
})
}
func customUIView() {
tabBarView.layer.shadowColor = UIColor.lightGray.cgColor
tabBarView.layer.shadowOpacity = 1
tabBarView.layer.shadowOffset = CGSize.zero
tabBarView.layer.shadowRadius = 3
}
#IBAction func dismissButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
//TableView
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return recipiesList.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellDescription") as! TableViewCellDescription
let recipies = recipiesList[indexPath.row]
cell.recipiesModuleLabel.text = recipies.detail?.description
return cell
}
}
At this moment the result is:
Table View Entries
Any ideas?
In your case you want to show details items in different row whereas you have array of RecipiesModel.
var recipiesList = [RecipiesModel]()
In case you can represent each modal object of array as a section and details object as their rows. You can do that as:
// TableView datasource and delegate methods
func numberOfSections(in tableView: UITableView) -> Int {
return recipiesList.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let modal = recipiesList[section]
return "\(modal.title ?? ""): \(modal.desc ?? "")"
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return recipiesList[section].detail?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellDescription") as! TableViewCellDescription
if let detailName = recipiesList[indexPath.section].detail?[indexPath.row] as? String {
cell.recipiesModuleLabel.text = detailName
} else {
cell.recipiesModuleLabel.text = ""
}
return cell
}

No data is showing up in my UITableView

My IBOutlet for songName is set up correctly, but for some reason
import UIKit
class QueueController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
let testUser = Profile.init(username: "test", followers: [], following: [])
let songOne = Song.init(name: "S1", UWR: testUser.username, genre: "rock", artist: "s1")
var moreSongs = [Song]()
moreSongs = [Song(name: "gah", UWR: testUser.username, genre: "gahh", artist: "GAH")]
Queue.createQueue("2321x", creator: testUser, firstSong: songOne, additionalSongs: moreSongs)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Queue.theQueue!.count
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if let feed = Queue.theQueue {
return feed.count
} else {
return 0
}
}
func songIndex(cellIndex: Int) -> Int {
return tableView.numberOfSections - cellIndex - 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let song = Queue.theQueue![songIndex(indexPath.section)]
let cell = tableView.dequeueReusableCellWithIdentifier("queueCell", forIndexPath: indexPath) as! QueueCell
//cell.textLabel?.text = song.name this doesnt work also
cell.songName.text = "asdad"
return cell
}
}
For my Queue class:
import UIKit
class Queue {
let creator:Profile!
let planetID:String!
let beginningSong: Song!
var feed:Array<Song>?
static var theQueue:Array<Song>?
init (id:String!, creator:Profile!, firstSong:Song!) {
self.planetID = id
self.creator = creator
self.beginningSong = firstSong
}
func addSong (song: Song) {
feed?.append(song)
}
static func createQueue (id:String!, creator:Profile!, firstSong:Song!, additionalSongs: [Song]) {
let temp = Queue(id: id, creator: creator, firstSong: firstSong)
for song in additionalSongs {
temp.addSong(song)
}
self.theQueue = temp.feed
}
}
Song class:
import UIKit
class Song {
let name:String!
let userWhoRequested:String!
let genre: String?
let artist: String?
init (name:String!, UWR:String!, genre:String?, artist:String?) {
self.name = name
self.userWhoRequested = UWR
self.genre = genre
self.artist = artist
}
}
class QueueCell: UITableViewCell {
#IBOutlet weak var songName:UILabel!
#IBOutlet weak var userPicture:UIImageView!
#IBOutlet weak var isCurrent:UIImageView!
}
The table view displays properly but no data shows up in my controller, and I'm not sure why. The reuse cell identifier is also correct. The data in viewDidLoad() is also in my app delegate's func application.
Thanks!
Your problem is with the feed inside your CreateQueue method, that was never initialized
And change
var feed:Array<Song>?
to
var feed = [Song]()

Transfer variables from one class to another class for table view

I am trying to transfer variables from one class into a table view class as follows (excellent code for the table view class).
I get the following error in class SecondViewController:
xnyCats = catRet.mainCats() throws an error Expected Declaration
How do I get class SecondViewController to inherit xnyCats from class XnYCategories?
import UIKit
import Foundation
class XnYCategories {
var catsXny: [String]
init(catsXny: [String]) {
self.catsXny = catsXny
}
func mainCats() -> [String] {
var catsXny = ["Sport", "Recreation", "Travel", "Cultural", "Music"]
return catsXny
}
}
let catRet = XnYCategories(catsXny: [""])
var xnyCats = [""]
xnyCats = catRet.mainCats()
xnyCats[1]
import UIKit
class SecondViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
#IBAction func displayTapped(sender : AnyObject) {
}
let textCellIdentifier = "TextCell"
let catRet = XnYCategories(catsXny: [""])
var xnyCats = [""]
xnyCats = catRet.mainCats() //throws an error 'Expected Declaration'
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return xnyCats.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! UITableViewCell
let row = indexPath.row
cell.textLabel?.text = xnyCats[row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
let row = indexPath.row
println(xnyCats[row] + String(row))
}
}
By checking your code i find out that you are not able to call the mainCats()function from other class so there are different ways to call a function
1: Create the class object and call the function for example
class Demo {
func display() {
println("Hello")
}
}
var d = Demo()
d.display()
2: Declare class function and call it. for example
class Demo {
class func display() {
println("Hello")
}
}
Demo.display()
Now make the following modification in your code and u get the result
class XnYCategories {
var catsXny: [String]
init (catsXny: [String]){
self.catsXny = catsXny
}
class func mainCats() -> [String] {
var catsXny = ["Sport", "Recreation", "Travel", "Cultural", "Music"]
return catsXny
}
}
let catRet = XnYCategories.mainCats()
println(catRet)

Resources