some problem about to show imageView from CoreData in TableView - ios

I saved the photo and name of the movie to CoreData. entity name is movieEntity
When I try to show a photo and name of a movie in tableView, I have a problem with the picture. The name of the movie successfully visible to tableView, but the photo of the movie is not visible.
class movieViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var movie: [NSManagedObject] = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "movieEntity")
do {
coreDataMoviePhoto = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
}
extension movieViewController: UITableViewDataSource, UITableViewDelegate{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return movie.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let movieData = movie[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "movieTableViewCell", for: indexPath) as! movieTableViewCell
cell.tableViewCellImageView.image = movieData.value(forKeyPath: "img") as? UIImage
cell.tableViewTextLabel.text = movieData.value(forKeyPath: "name") as? String
return cell
}
}
here is movieTableViewCell
class CoreDataWatchlistTableViewCell: UITableViewCell {
#IBOutlet weak var tableViewTextLabel: UILabel!
#IBOutlet weak var tableViewCellImageView: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
}
}

As you saving image data not image in so use
if let data = movieData.value(forKeyPath: "img") as? Data{
cell.tableViewCellImageView.image = UIImage(data:data)
}else{
cell.tableViewCellImageView.image = somePlaceholderImage
}
hope its help

Related

Class 'TableViewController' has no initializers [duplicate]

This question already has answers here:
Class 'ViewController' has no initializers in swift
(8 answers)
Closed last month.
import UIKit
import CoreData
class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var titleArray = [String]()
var idArray = [UUID()]
var chosenTitle = ""
var chosenTitleID : UUID
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.topItem?.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.add, target: self, action: #selector(addButtonClicked))
tableView.delegate = self
tableView.dataSource = self
getData()
}
func getData() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Places")
request.returnsObjectsAsFaults = false
do {
let results = try context.fetch(request)
if results.count > 0 {
self.titleArray.removeAll(keepingCapacity: false)
self.idArray.removeAll(keepingCapacity: false)
for result in results as! [NSManagedObject] {
if let title = result.value(forKey: "title") as? String {
self.titleArray.append(title)
}
if let id = result.value(forKey: "id") as? UUID {
self.idArray.append(id)
}
tableView.reloadData()
}
}
} catch {
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = titleArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titleArray.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
chosenTitle = titleArray[indexPath.row]
chosenTitleID = idArray[indexPath.row]
performSegue(withIdentifier: "toDetailsVC", sender: nil)
}
I have a problem with Swift class. I have a swift file for UITableViewController class. I had "Class 'TableViewController' has no initializers" problem.
I didn't find anything but the code says TableViewController has no initializers. I don't understand this problem. I have version 14.2.
Thanks for your responses.
You can make chosenTitleID property optional(var chosenTitleID: UUID?) or provide the default value to chosenTitleID because TableViewController class contains non-optional property.

Displaying images fetched from firebase in tableview

I am trying to retrieve data from firebase and display them in a tableview but my code for some reason is not working. I am getting the images and appending them into a list but that list is not having any data outside the else block.
With my implementation, I am getting a blank tableview. Could someone help with me this please?
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var tableView: UITableView!
let db = Firestore.firestore()
var usersReference = Firestore.firestore().collection("users")
var storageReference = Storage.storage().reference()
var imagesList = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
usersReference.addSnapshotListener { [self] (querySnapshot, error) in
querySnapshot?.documents.forEach() {
(document) in
let uid = document.data()["uid"] as! String
let imagePath = "profilePictures/\(uid).jpg"
let imgRef = storageReference.child(imagePath)
imgRef.getData(maxSize: 1 * 2048 * 2048) { data, error in
if let error = error {
print(String(describing: error))
}
else {
DispatchQueue.main.async {
let image = UIImage(data: data!)
imagesList.append(image!)
print("inside viewDidLoad: ", imagesList.count)
}
}
}
}
}
print(imagesList.count)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return imagesList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "imageCell", for: indexPath)
print("cellForRowAt: ",imagesList.count)
cell.textLabel?.text = "\(indexPath.row)"
cell.imageView?.image = imagesList[indexPath.row]
return cell
}
This is how my simulator looks like when I run the code: compiled code .

can we pass data from table cell to table view where both are xib files?

I want to pass table cell data (xib file) to table view (also a xib file). I have tried passing the data using the following piece of code but did not get an appropriate result.
PropertyCell.swift
import UIKit
class PropertyCell: UITableViewCell {
#IBOutlet weak var propertyCodeLbl: UILabel!
#IBOutlet weak var addressLbl: UILabel!
}
I have attached the screenshot for PropertyCell below -
PropertyCell.xib
PropertyCell.xib file
PropertyTableVC.swift
import UIKit
import Alamofire
class PropertyTableVC: UITableViewController {
#IBOutlet var propertyTabel: UITableView!
let URL_Landlord_Property_List = "http://127.0.0.1/source/api/LandlordPropertyList.php"
var count: Int = 0
var landlordPropertyArray: [PropertyList]? = []
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
propertyTabel.dataSource = self
propertyTabel.delegate = self
let nibName = UINib(nibName: "PropertyCell", bundle:nil)
self.propertyTabel.register(nibName, forCellReuseIdentifier: "Cell")
}
func fetchData(){
let urlRequest = URLRequest(url: URL(string: URL_Landlord_Property_List)!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if error != nil{
print(error!)
return
}
print(data!)
self.landlordPropertyArray = [PropertyList]()
self.count = (self.landlordPropertyArray?.count)!
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]
if let datafromjson = json["landlords_property_list"] as? [[String: AnyObject]] {
print(datafromjson)
for data in datafromjson{
var property = PropertyList()
if let id = data["ID"] as? Int,let code = data["Code"] as? String, let address1 = data["Address"] as? String
{
property.id = id
property.code = code
property.address1 = address1
}
self.landlordPropertyArray?.append(property)
}
print(self.landlordPropertyArray)
}
DispatchQueue.main.async {
self.propertyTabel.reloadData()
}
}catch let error {
print(error)
}
}
task.resume()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (landlordPropertyArray?.count)!
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Configure the cell...
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! PropertyCell
cell.propertyCodeLbl.text = self.landlordPropertyArray?[indexPath.item].code
cell.addressLbl.text = self.landlordPropertyArray?[indexPath.item].address1
return cell
}
}
Attached the screenshot for Property Table below -
PropertyTableVC.xib
PropertyTableVC.xib file
Your TableViewCell :
import UIKit
protocol yourProtocolName { //add protocol here
func getDataFromTableViewCellToViewController (sender : self) //* as you need to pass the table view cell, so pass it as self
}
class PropertyCell: UITableViewCell {
#IBOutlet weak var propertyCodeLbl: UILabel!
#IBOutlet weak var addressLbl: UILabel!
var delegate : yourProtocolName? //set a delegate
override func awakeFromNib() {
super.awakeFromNib()
if delegate != nil {
delegate.getDataFromTableViewCellToViewController(sender :self) *
}
}
}
And your ViewController :
import UIKit
import Alamofire
class PropertyTableVC: UITableViewController,yourProtocolName { //conform to the protocol you created in tableViewCell
#IBOutlet var propertyTabel: UITableView!
let URL_Landlord_Property_List = "http://127.0.0.1/source/api/LandlordPropertyList.php"
var count: Int = 0
var landlordPropertyArray: [PropertyList]? = []
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
propertyTabel.dataSource = self
propertyTabel.delegate = self
let nibName = UINib(nibName: "PropertyCell", bundle:nil)
self.propertyTabel.register(nibName, forCellReuseIdentifier: "Cell")
}
func fetchData(){
let urlRequest = URLRequest(url: URL(string: URL_Landlord_Property_List)!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if error != nil{
print(error!)
return
}
print(data!)
self.landlordPropertyArray = [PropertyList]()
self.count = (self.landlordPropertyArray?.count)!
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]
if let datafromjson = json["landlords_property_list"] as? [[String: AnyObject]] {
print(datafromjson)
for data in datafromjson{
var property = PropertyList()
if let id = data["ID"] as? Int,let code = data["Code"] as? String, let address1 = data["Address"] as? String
{
property.id = id
property.code = code
property.address1 = address1
}
self.landlordPropertyArray?.append(property)
}
print(self.landlordPropertyArray)
}
DispatchQueue.main.async {
self.propertyTabel.reloadData()
}
}catch let error {
print(error)
}
}
task.resume()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (landlordPropertyArray?.count)!
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Configure the cell...
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! PropertyCell
cell.propertyCodeLbl.text = self.landlordPropertyArray?[indexPath.item].code
cell.addressLbl.text = self.landlordPropertyArray?[indexPath.item].address1
return cell
}
func getDataFromTableViewCellToViewController(sender :UITableViewCell) {
//make a callback here
}
}
(*) Marked fields are updated code
Call fetchData() function after tableview delegate and datasource assigning
propertyTabel.dataSource = self
propertyTabel.delegate = self
Updated answer is
Create Cell Class like this
import UIKit
class YourTableViewCell: UITableViewCell {
#IBOutlet weak var profileImageView: UIImageView!
#IBOutlet weak var userNameLabel: UILabel!
#IBOutlet weak var timeDateLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
self.backgroundColor = UIColor.tableViewBackgroundColor()
self.selectionStyle = .none
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
class func cellForTableView(tableView: UITableView, atIndexPath indexPath: IndexPath) -> YourTableViewCell {
let kYourTableViewCell = "YourTableViewCellIdentifier"
tableView.register(UINib(nibName:"RRLoadQuestionsTableViewCell", bundle: Bundle.main), forCellReuseIdentifier: kYourTableViewCell)
let cell = tableView.dequeueReusableCell(withIdentifier: kYourTableViewCell, for: indexPath) as! YourTableViewCell
return cell
}
}
Then create UIViewController Class and place UITableView on it and link with outlet
class YourViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextViewDelegate {
#IBOutlet weak var tableView: UITableView!
var dataSource = [LoadYourData]()
// MARK: - Init & Deinit
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: "YourViewController", bundle: Bundle.main)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
setupViewControllerUI()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
}
// MARK: - UIViewController Helper Methods
func setupViewControllerUI() {
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
tableView.delegate = self
tableView.dataSource = self
loadData()
}
func loadData() {
// Write here your API and reload tableview once you get response
}
// MARK: - UITableView Data Source
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = YourTableViewCell.cellForTableView(tableView: tableView, atIndexPath: indexPath)
// assign here cell.name etc from dataSource
return cell
}

Pass data between tableViews by using storyboard instantiateviewcontrollerwithidentifier

I'm trying to pass data from one tableView to to a static one. I'm not using a segue and using instantiateviewcontrollerwithidentifier instead, i dont know where i'm going wrong here. I'm using cloudkit and fetching ckRecords from icloud. i have a collectionView first where i tap a cell and displays books corresponding to that cell. However when they are displayed in the cells, i want to tap on the cell to bring up the detailViewController. It's not working at the moment and can't get the head around why.
import CloudKit
class DetailViewController: UITableViewController {
#IBOutlet weak var aboutBookLabel: UILabel!
#IBOutlet weak var bookLengthLabel: UILabel!
#IBOutlet weak var amazonPriceLabel: UILabel!
#IBOutlet weak var ebayPriceLabel: UILabel!
#IBOutlet weak var websitePriceLabel: UILabel!
#IBOutlet weak var authorLabel: UILabel!
#IBOutlet weak var bookTitleLabel: UILabel!
#IBOutlet weak var bookImageView: UIImageView!
var bookRecord: CKRecord?
override func viewDidLoad() {
super.viewDidLoad()
populateData()
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cell.backgroundColor = UIColor(red: 27.0/255.0, green: 28.0/255.0 , blue: 32.0/255.0, alpha: 1.0)
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
func populateData() {
aboutBookLabel.text = bookRecord?.object(forKey: "description") as? String
bookLengthLabel.text = bookRecord?.object(forKey: "length") as? String
amazonPriceLabel.text = bookRecord?.object(forKey: "amazon") as? String
ebayPriceLabel.text = bookRecord?.object(forKey: "ebay") as? String
websitePriceLabel.text = bookRecord?.object(forKey: "authorPrice") as? String
authorLabel.text = bookRecord?.object(forKey: "author") as? String
bookTitleLabel.text = bookRecord?.object(forKey: "name") as? String
if let imageFile = bookRecord?.object(forKey: "image") as? CKAsset {
bookImageView.image = UIImage(contentsOfFile: imageFile.fileURL.path)
}
}
}
class BooksViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
let cellIdentifier = "bookCell"
var books = [CKRecord]()
var sectorTitle = "language"
override func viewDidLoad() {
super.viewDidLoad()
registerNib()
fetchBooksFromCloud()
configureTableView()
}
func fetchBooksFromCloud() {
books = [CKRecord]()
books.removeAll()
tableView.reloadData()
let cloudContainer = CKContainer.default()
let publicDatabase = cloudContainer.publicCloudDatabase
let predicate = buildBookPredicate()
let query = CKQuery(recordType: "Book", predicate: predicate)
query.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let queryOperation = CKQueryOperation(query: query)
queryOperation.desiredKeys = ["name", "author", "image", "format", "description", "length", "amazon", "ebay", "authorPrice"]
queryOperation.queuePriority = .veryHigh
queryOperation.resultsLimit = 25
queryOperation.recordFetchedBlock = { (record) -> Void in
self.books.append(record)
}
DispatchQueue.global(qos: .userInteractive).async {
queryOperation.queryCompletionBlock = { (cursor, error) -> Void in
if let error = error {
print("Download failed \(error.localizedDescription)")
return
}
print("Download Successful")
OperationQueue.main.addOperation {
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
}
queryOperation.qualityOfService = .userInteractive
publicDatabase.add(queryOperation)
}
private func buildBookPredicate() -> NSPredicate {
return NSPredicate(format:"self contains '\(sectorTitle)'")
}
extension BooksViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return books.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier , for: indexPath) as! BookCell
let book = books[indexPath.row]
let bookName = book.object(forKey: "name") as? String
let authorName = book.object(forKey: "author") as? String
let image = book.object(forKey: "image") as? CKAsset
let formatName = book.object(forKey: "format") as? String
cell.nameLabel.text = bookName
cell.authorLabel.text = authorName
cell.formatLabel.text = formatName
cell.bookImageName.image = UIImage(contentsOfFile: image!.fileURL.path)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let record = books[indexPath.row]
if let detailVC = storyboard?.instantiateViewController(withIdentifier: "DetailVC") as? DetailViewController {
detailVC.bookRecord = record
navigationController?.pushViewController(detailVC, animated: true)
}
tableView.deselectRow(at: indexPath, animated: true)
}
The storyboard property of UIViewController represents the storyboard from which the view controller originated. If you want to load another view controller from the same storyboard you can use it.
However, if you want to load the UIViewController from another storyboard you have to create the UIStoryboard instance first.
You can do it like this.
UIStoryboard(name: "YourStoryboardName", bundle: nil).instantiateViewController(withIdentifier: "DetailVC")

how to put 2 text in 1 row when you add?

import UIKit
import CoreData
class ViewController: UIViewController , UITableViewDataSource , UITableViewDelegate {
#IBOutlet weak var text1: UITextField!
#IBOutlet weak var text2: UITextField!
#IBOutlet weak var ttableview: UITableView!
/////
//CoreData
func saveName(name: String) {
let appDel:AppDelegate = UIApplication.shared.delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Zain",in:context)
let person1 = NSManagedObject(entity: entity!,insertInto: context)
let person2 = NSManagedObject(entity: entity!,insertInto: context)
person1.setValue(name, forKey: "man1")
person2.setValue(name, forKey: "man2")
do {
try context.save()
//5
array1.insert(person1, at: 0)
array2.insert(person2, at: 0)
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
/////
#IBAction func Add(_ sender: Any) {
self.saveName(name: text1.text!)
self.saveName(name: text2.text!)
self.ttableview.reloadData()
}
//deleat row and tableview and arry
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
array1.remove(at: indexPath.row)
array2.remove(at: indexPath.row)
ttableview.deleteRows(at: [indexPath], with: .fade)
let appDel:AppDelegate = UIApplication.shared.delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.persistentContainer.viewContext
context.delete(array1[indexPath.row] as NSManagedObject)
context.delete(array2[indexPath.row] as NSManagedObject)
do {
try context.save()
} catch _ {
print("remove object error")
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array1.count
}
func ttableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array2.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = ttableview.dequeueReusableCell(withIdentifier: "cell") as! Cell
let person1 = array1[indexPath.row]
let person2 = array2[indexPath.row]
cell.lable1.text = person1.value(forKey: "man1") as! String?
cell.lable2.text = person2.value(forKey: "man2") as! String?
return cell
}
var array1 = [NSManagedObject]()
var array2 = [NSManagedObject]()
override func viewDidLoad() {
super.viewDidLoad()
ttableview.delegate = self
ttableview.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let appDel:AppDelegate = UIApplication.shared.delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Zain")
do {
let results = try context.fetch(fetchRequest)
array1 = results as! [NSManagedObject]
array2 = results as! [NSManagedObject]
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
}
Why don't you just use two labels / textFields in your tableview cells?
You will need a custom uitableviewcell for this.

Resources