I am trying to display items in my List entity on a table view. I believe my issue is a type casting one, but after researching a bit, I've been unable to find a solution. My exact error is "Cannot assign value of type 'List' to type 'String?'.
Below is the code:
import UIKit
import CoreData
class ToBeastViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var items = [List]()
let matthewsManagedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let request = NSFetchRequest(entityName: "List")
do {
let response = try matthewsManagedObjectContext.executeFetchRequest(request)
print("Sucess!")
let arrayList = response as! [List]
for item in arrayList {
print(item.item)
}
}
catch {
print("Failed!")
} // numberOfRowsInSection end
return items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("MyCell")! as UITableViewCell
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath)
// var itemString = List as! item
cell.textLabel?.text = items[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("You selected cell #\(indexPath.row)!")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The issue is with the line:
cell.textLabel?.text = items[indexPath.row]
...or at least that's my understanding. I apologize if the formatting is poor or if I am missing information that may help. Some of my attempts to solve this are commented out. Thank you for any help!
Edit*
Below is the code from the View that takes text input and adds it to List:
import UIKit
import CoreData
class JustBeastItViewController: UIViewController {
let matthewsManagedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
// var items = [List]()
#IBAction func doneButtonPressed(sender: UIBarButtonItem) {
let newManagedObject = NSEntityDescription.insertNewObjectForEntityForName("List", inManagedObjectContext: matthewsManagedObjectContext)
let newItem = newManagedObject as! List
newItem.item = justBeastItTextField.text
do {
try matthewsManagedObjectContext.save()
print("It was successful!")
}
catch {
print("There was an error!")
}
let request = NSFetchRequest(entityName: "List")
do {
let response = try matthewsManagedObjectContext.executeFetchRequest(request)
print("Sucess!")
let arrayList = response as! [List]
for item in arrayList {
print(item.item)
}
}
catch {
print("Failed!")
}
}
#IBOutlet weak var justBeastItTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Related
I am a novice to swift. This is my first assignment for UI development. I have done the exercise perfectly and the tableView showed up as expected. The code is as below:
import UIKit
class ViewController: UIViewController {
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tableView.delegate = self
tableView.dataSource = self
}
}
extension ViewController: UITableViewDelegate{
}
extension ViewController: UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "gameScoreCell", for: indexPath)
cell.textLabel?.text = "hello world"
cell.detailTextLabel?.text = "score"
return cell
}
}
However, when I followed the same step and tried to integrate it with my project (with a navigation controller), the table view does not show up. Did I miss anything?
import UIKit
class HightScoreVC: UIViewController {
#IBOutlet var rankingTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
rankingTable.delegate = self
rankingTable.dataSource = self
}
}
extension HightScoreVC: UITableViewDelegate{
}
extension HightScoreVC: UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "gameScoreCell", for: indexPath)
cell.textLabel?.text = "hello world"
cell.detailTextLabel?.text = "123"
return cell
}
}
I think you must register your cell in ViewDidLoad():
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
rankingTable.delegate = self
rankingTable.dataSource = self
rankingTable.register(UITableViewCell.self, forCellReuseIdentifier: "gameScoreCell")
}
Points to keep in mind while working with tableview in swift.
Make sure constriants of tableview are given properly.
You have connected the class to the view controller in the identity inspector.
Provide delegate and datasource in viewDidLoad() itself rather than storyboard for better practice.
If you are creating xib for a cell, make sure you have registered the cell for your tableview, or if you are providing prototype cell, make sure you provide dequeueReusableCell() method and initialize your cell for some specific class.
Simple example for a tableview with some prototype cell
import UIKit
class UsersListViewController: UIViewController, Storyboarded {
//MARK: - Variables
var coordinator: AuthenticationCoordinator?
var usersList: UsersList?
//MARK: - Outlets
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var progressBar: UIActivityIndicatorView!
#IBOutlet weak var btnAddUser: UIButton!
//MARK: - UIViewController
override func viewDidLoad() {
super.viewDidLoad()
initializeView()
getUsersList()
}
//MARK: - Actions
#IBAction func addUserAction(_ sender: UIButton) {
coordinator?.presentAddUser()
}
//MARK: - File private functions
fileprivate func initializeView() {
self.title = "Users list"
progressBar.startAnimating()
btnAddUser.layer.masksToBounds = true
btnAddUser.layer.cornerRadius = btnAddUser.frame.height / 2
tableView.delegate = self
tableView.dataSource = self
}
fileprivate func getUsersList() {
guard let url = URL(string: ApiUrl.delayResponseURL.rawValue) else { return }
var request = URLRequest(url: url)
request.httpMethod = "GET"
URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil else { return }
guard let data = data else { return }
guard let response = response as? HTTPURLResponse, (200 ..< 299) ~= response.statusCode else { return }
do {
guard let jsonObject = try JSONSerialization.jsonObject(with: data) as? [String: Any] else { return }
guard let prettyJsonData = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted) else { return }
guard let responseData = try? JSONDecoder().decode(UsersList.self, from: prettyJsonData) else { return }
self.usersList = responseData
DispatchQueue.main.async {
self.progressBar.stopAnimating()
self.progressBar.alpha = 0
self.tableView.reloadData()
}
} catch {
return
}
}.resume()
}
}//End of class
//MARK: - UITableViewDelegate
extension UsersListViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let index = usersList?.data[indexPath.row].userID {
coordinator?.startSingleUserVC(index)
tableView.deselectRow(at: indexPath, animated: true)
}
}
}//End of extension
//MARK: - UITableViewDataSource
extension UsersListViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "singleUserCell") as? SingleUserTableViewCell {
if let url = URL(string: usersList?.data[indexPath.row].avatar ?? "") {
DispatchQueue.global().async {
guard let data = try? Data(contentsOf: url) else { return }
val currentUser = self.usersList?.data[indexPath.row]
DispatchQueue.main.async {
cell.initCell(data, currentUser.firstName, currentUser.email)
}
}
}
return cell
}
return UITableViewCell()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return usersList?.data.count ?? 1
}
}//End of extension
So I'm an absolute beginner with xcode 11.4 / swift 5.
I found a tutorial on youtube where I wanted to program.
Here I have a problem that the viewtable is not updated after a new entry.
The database was created successfully and the entries that were entered are also displayed. But as I said, as soon as you create a new entry, you won't see it.
Can you help me find the bug?
Thanks a lot
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// MARK: - Outlet
#IBOutlet weak var tableView: UITableView!
// MARK: - View - Lifecylce
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
CoreDataManager.shared.loadItems()
self.tableView.reloadData()
}
// MARK: - TableView methodes
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return CoreDataManager.shared.getNumberofItems()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let todo = CoreDataManager.shared.getTodoItems(index: indexPath.row)
cell.textLabel?.text = todo.name
return cell
}
}
import UIKit
import CoreData
class CoreDataManager {
static let shared = CoreDataManager()
var todos = [Todo]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
private init() {
loadItems()
}
func createObj(name: String) {
let todo = NSEntityDescription.insertNewObject(forEntityName: "Todo", into: context) as! Todo
todo.name = name
todo.completed = false
saveContext()
}
func loadItems() {
let request = NSFetchRequest<Todo>(entityName: "Todo")
do {
todos = try context.fetch(request)
} catch {
print(error.localizedDescription)
}
}
//MARK: - Count Array
func getNumberofItems() -> Int {
return todos.count
}
func getTodoItems(index: Int) -> Todo {
return todos[index]
}
func saveContext(){
do {
try context.save()
} catch {
print(error.localizedDescription)
}
}
}
I want to display data from CoreData into a tableview, im working on favoris, im adding my events on favoris and i want to display it inside a tableview, there is my code :
var lists : [NSManagedObject] = [] {
didSet {
favorisEventTableView.reloadData()
}
}
#IBOutlet weak var favorisEventTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
favorisEventTableView.dataSource = self
favorisEventTableView.delegate = self
loadFavoris()
// Do any additional setup after loading the view.
}
override func viewWillAppear(_ animated: Bool) {
favorisEventTableView.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return lists.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = favorisEventTableView.dequeueReusableCell(withIdentifier: "FavorisCell")
let contentView = cell?.viewWithTag(0)
let eventId = contentView?.viewWithTag(4) as! UILabel
let item = lists[indexPath.row]
eventId.text = String((item.value(forKey: "id_event") as! Int))
return cell!
}
func loadFavoris() {
let appDelegate = UIApplication.shared.delegate as? AppDelegate
let coreContext = appDelegate?.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Favoris")
do {
lists = try coreContext!.fetch(fetchRequest)
print(lists)
} catch let error as NSError {
print(error.userInfo)
}
}
But it's not displaying anything, maybe the problem on the add function ? im sure it works cause i get "saved" on the console, any help please?
PS: entity "Favoris" has only one attribute "id_event" which is an integer
You need to add loadFavoris inside viewDidLoad not cellForRowAt
override func viewDidLoad() {
super.viewDidLoad()
favorisEventTableView.dataSource = self
favorisEventTableView.delegate = self
loadFavoris()
}
You need to reload your table view every change on your list. you can do it like that
var lists : [NSManagedObject] = [] {
didSet {
tableView.reloadData()
}
}
Don't forget assign the delegate and dataSource protocols of tableView and fetch the data in viewDidLoad() function
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
loadFavoris()
}
I'm coding a Note App in Swift 4. The root ViewController (NoteListViewController) gets populated when secondViewController (ComposeNoteViewController) Textfield and TextView are populated.
The problem is when I press a populated TableView cell, rather than fetch and display the content, it opens a fresh instance of theComposeNoteViewController.
import UIKit
import CoreData
class NoteListTableViewController: UITableViewController {
var noteListArray = [NoteListItem]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
loadNoteListItem()
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return noteListArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "NoteListItemCell", for: indexPath)
cell.textLabel?.text = noteListArray[indexPath.row].title
return cell
}
//MARK: - TABLEVIEW DELEGATE METHODS
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "goToComposeNote", sender: self)
tableView.deselectRow(at: indexPath, animated: true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.destination as! ComposeNoteViewController
if let indexPath = tableView.indexPathForSelectedRow {
destinationVC.selectedNoteList = noteListArray[indexPath.row]
}
}
import UIKit
import CoreData
class ComposeNoteViewController: UIViewController {
var noteComposeItemsArray = [ComposeNote]()
var noteListArray = [NoteListItem]()
// let noteListController = NoteListTableViewController()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var selectedNoteList : NoteListItem? {
didSet {
loadComposeItem()
}
}
#IBOutlet weak var noteTextView: UITextView!
#IBOutlet weak var noteTextField: UITextField!
#IBAction func noteSavePressed(_ sender: UIBarButtonItem) {
let newNoteTitleItem = NoteListItem(context: context)
let newComposeNote = ComposeNote(context: context)
newNoteTitleItem.title = noteTextField.text!
newComposeNote.note = noteTextView.text!
newComposeNote.parentTitleNote = selectedNoteList
noteComposeItemsArray.append(newComposeNote)
noteListArray.append(newNoteTitleItem)
saveComposeItems()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func saveComposeItems() {
do {
try context.save()
}catch {
print("Error saving context \(error)")
}
reloadInputViews()
}
func loadComposeItem() {
let request : NSFetchRequest<ComposeNote> = ComposeNote.fetchRequest()
let predicate = NSPredicate(format: "parentTitleNote.title MATCHES %#", selectedNoteList!.title!)
request.predicate = predicate
do {
noteComposeItemsArray = try context.fetch(request)
}catch {
print("Can't load Items")
}
reloadInputViews()
}
}
I'm loading some data from a web server and I'm getting ambiguous reference to member tableview numberOfRowsInSection? Below is my swift file. What am i missing here?
TableViewController.swift
import UIKit
class TableViewController: UITableViewController {
var viewModel:ViewModel!
override func viewDidLoad() {
super.viewDidLoad()
self.viewModel = ViewModel()
self.tableView.delegate = viewModel
self.tableView.dataSource = viewModel
self.tableView.registerNib(UINib(nibName: "TableViewCell", bundle: NSBundle.mainBundle()), forCellReuseIdentifier: tableViewCellIdentifier)
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 50;
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
ViewModel.swift
import UIKit
class ViewModel: NSObject,UITableViewDelegate, UITableViewDataSource, UICollectionViewDelegate, UICollectionViewDataSource {
var dataArrayPosts: NSArray!
var posts:[Post] = []
override init() {
super.init()
let myURL = NSURL(string: "mydomainURLhere");
let requestPosts = NSMutableURLRequest(URL: myURL!);
requestPosts.HTTPMethod = "POST";
let postStringVars = ""
requestPosts.HTTPBody = postStringVars.dataUsingEncoding(NSUTF8StringEncoding);
let taskPosts = NSURLSession.sharedSession().dataTaskWithRequest(requestPosts){ data, response, error in
if error != nil{
print("error\(error)");
return;
}
do {
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
//print(json)
if let category = json["Posts"] as? NSMutableArray{
//print(category)
_ = category
self.dataArrayPosts = json["Posts"] as! NSMutableArray;
dispatch_async(dispatch_get_main_queue()) {
self.posts.removeAll()
for item in self.dataArrayPosts {
let post = Post(postDesc: (item["postDesc"] as? String)!,imageName: (item["imageName"] as? String)!,bName: (item["bName"] as? String)!,postDate: (item["postDate"] as? String)!,postShowsUntil:(item["postShowsUntil"] as? String)!)
self.posts.append(post)
// Ambiguous on reloadData???????
self.tableView.reloadData()
}
}
}else{
dispatch_async(dispatch_get_main_queue()) {
print("Nothing Was Found")
}
}
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
taskPosts.resume()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(tableViewCellIdentifier, forIndexPath: indexPath) as! TableViewCell
let post = posts[indexPath.row]
cell.quoteTextLabel.text = post.postDesc
cell.nameLabel.text = post.bName
if let imageName = post.imageName where !imageName.isEmpty{
cell.photoView?.image = UIImage(named: imageName)
cell.photoWidthConstraint.constant = kDefaultPhotoWidth
cell.photoRightMarginConstraint.constant = kDefaultPhotoRightMargin
}
else {
cell.photoView?.image = nil
cell.photoWidthConstraint.constant = 0
cell.photoRightMarginConstraint.constant = 0
}
cell.contentView.setNeedsLayout()
cell.contentView.layoutIfNeeded()
return cell
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return posts.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(collectionViewCellIdentifier, forIndexPath: indexPath) as! CollectionViewCell
return cell
}
}
None of the things that ViewModel inherits from expose a tableView property, your ViewModel needs a reference to your UITableViewController. As the ViewController owns the ViewModel it should be a weak reference, something like the following
class ViewModel: NSObject,UITableViewDelegate, UITableViewDataSource, UICollectionViewDelegate, UICollectionViewDataSource {
weak let tableViewController:UITableViewController
var dataArrayPosts: NSArray!
var posts:[Post] = []
override init(controller:UITableViewController) {
self.tableViewController = controller
super.init()
// ...
self.tableViewController.tableView.reloadData()
}
class TableViewController: UITableViewController {
var viewModel:ViewModel!
override func viewDidLoad() {
super.viewDidLoad()
self.viewModel = ViewModel(controller:self)
// ...
}