Swift - tableviewcell returns empty using custom cell - ios

I am new to swift programming and would need some help to check what is wrong in my tableviewcell. I have tried alot of great suggestions on stackoverflow.( make sure your outlets are connected, set delegate and datasource of your tableview to self)
This is my ViewController:
import UIKit
class CharacterViewController: UIViewController, UITableViewDataSource, UITableViewDelegate , APIControllerProtocol {
#IBOutlet weak var CharacterInfoView: UITableView!
var apiController:APIController!
var dataArray: [[String:Any]]?
var processcharacter= [CharacterListModel]()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor=UIColor.white
self.CharacterInfoView.estimatedRowHeight = 44
self.CharacterInfoView.rowHeight = UITableViewAutomaticDimension
self.CharacterInfoView.dataSource = self
self.CharacterInfoView.delegate = self
apiController = APIController()
apiController.delegate=self
self.navigationItem.title = "Character"
self.view.showLoading()
apiController.getCharacterData{ (statusCode, data, response, error) -> () in
self.view.stopLoading()
if(statusCode == nil)
{
self.view.showServiceNotAvailableMessage(self)
}
if !(error == nil)
{
self.view.showServiceNotAvailableMessage(self)
}
if statusCode == 200
{
do
{
self.processcharacter= CharacterListData.processData(data: data)
self.CharacterInfoView.reloadData()
}
catch(_ as NSError)
{
}
}
else
{
return
}
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.dataArray == nil
{
return 0
}
else
{
return processcharacter.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:"Cell", for:indexPath) as! CharacterTableViewCell
var processcharacters= processcharacter[indexPath.row]
cell.location.text = processcharacters.location
cell.name.text = processcharacters.name
cell.characterID.text = processcharacters.characterID
cell.time.text = processcharacters.lastlocatedtime
if wecares.sos == true {
processcharacters.imagebutton = UIImage(named: "sos_icon")!
}
else{
processcharacters.imagebutton = UIImage(named: "null_button")!
}
cell.button.image = processcharacters.imagebutton
return cell
}
func reachabilityChanged(_ status: Bool) {
}
}
This is my subclass for my ViewController:
import Foundation
class CharacterListDataHelper: NSObject {
static func processData(data: AnyObject?) -> [CharacterListModel]
{
var modelList:[CharacterListModel] = [CharacterListModel]()
let darr = try? JSONSerialization.jsonObject(with: data! as! Data, options: .mutableLeaves) as! [[String:Any]]
var dataModel:CharacterListModel
for obj in darr!
{
dataModel = CharacterListModel()
dataModel.location = obj["playerLocation"] as! String
dataModel.name = obj["playerName"] as! String
dataModel.characterID= obj["playerID"] as! String
dataModel.lastlocatedtime = obj["lastUpdatedTime"] as! String
}
modelList.append(dataModel)
}
return modelList
}
}
This is my Model:
import Foundation
struct CharacterListModel {
var name: String?
var characterID: String?
var location: String?
var lastlocatedtime: String?
var imagebutton: UIImage?
var sos: Bool?
}
This is my TableViewCell:
class CharacterTableViewCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var characterID: UILabel!
#IBOutlet weak var location: UILabel!
#IBOutlet weak var lastlocatedtime: UILabel!
#IBOutlet weak var button: 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
}
Thanks in advance!

Don't fetch data in viewDidLoad() method. Fetch in viewWillAppear and reload after getting data.

Related

ios Swift Items do not get added to cart

When I click on “Add” Button below, the products do not get added to the cart and the Checkout (0) does not increase to Checkout (1) etc. What am I doing wrong ?
-- Original issue resolved after reading #Larme's first comment. It was a rookie mistake(I had forgotten to put cell.delegate = self in tableView(_ tableView:, cellForRowAt: in ProductViewController). Now, I have some other problemin CartViewController(See Edit please) --
posting relevant code -
struct Product -
import UIKit
struct Product:Equatable {
let name : String
var quantity : Int
var price : Double
let imagename: UIImage
// var subTotal : Double {
//return Double(quantity) * price }
}
var products = [Product(name: "a", quantity: 5, price: 5.0,imagename:#imageLiteral(resourceName: "PeasImge")),
Product(name: "b", quantity: 10, price: 10.0, imagename:#imageLiteral(resourceName: "CakeImage")),]
class ProductViewController -
import UIKit
class ProductViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
fileprivate var cart = Cart()
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self }
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//Workaround to avoid the fadout the right bar button item
self.navigationItem.rightBarButtonItem?.isEnabled = false
self.navigationItem.rightBarButtonItem?.isEnabled = true
//Update cart if some items quantity is equal to 0 and reload the product table and right button bar item
cart.updateCart()
self.navigationItem.rightBarButtonItem?.title = "Checkout (\(cart.items.count))"
tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/* override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showCart" {
if let cartViewController = segue.destination as? CartViewController {
cartViewController.cart = self.cart
}
}
}*/
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return products.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProductTableViewCell") as! ProductTableViewCell
let product = products[indexPath.item]
cell.delegate = self // original issue was here, now resolved.
cell.name?.text = product.name
cell.imageView?.image = product.imagename
cell.setButton(state: self.cart.contains(product: product))
// Configure YourCustomCell using the outlets that you've defined.
return cell
}
}
extension ProductViewController: CartDelegate {
// MARK: - CartDelegate
func updateCart(cell: ProductTableViewCell) {
guard let indexPath = tableView.indexPath(for: cell) else { return }
let product = products[indexPath.item]
//Update Cart with product
cart.updateCart(with: product)
self.navigationItem.rightBarButtonItem?.title = "Checkout (\(cart.items.count))"
}
}
class ProductTableViewCell-
import UIKit
protocol CartDelegate {
func updateCart(cell: ProductTableViewCell)
}
class ProductTableViewCell: UITableViewCell {
weak var myParent:ProductViewController?
#IBOutlet weak var name: UILabel!
#IBOutlet weak var price: UILabel!
#IBOutlet weak var imagename: UIImageView!
#IBOutlet weak var addToCartButton: UIButton!
var delegate: CartDelegate?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
addToCartButton.layer.cornerRadius = 5
addToCartButton.clipsToBounds = true
}
func setButton(state: Bool) {
addToCartButton.isSelected = state
addToCartButton.backgroundColor = (!addToCartButton.isSelected) ? .black : .red
}
#IBAction func addToCart(_ sender: Any) {
setButton(state: !addToCartButton.isSelected)
self.delegate?.updateCart(cell: self)
}
}
class CartItem
import Foundation
class CartItem {
var quantity : Int = 1
var product : Product
/* var subTotal : Float { get { return Float(product.price) * Float(quantity) } } */
init(product: Product) {
self.product = product
}
}
class Cart -
import Foundation
class Cart {
var items : [CartItem] = []
}
extension Cart {
/* var total: Float {
get { return items.reduce(0.0) { value, item in
value + item.subTotal
}
}
}*/
var totalQuantity : Int {
get { return items.reduce(0) { value, item in
value + item.quantity
}
}
}
func updateCart(with product: Product) {
if !self.contains(product: product) {
self.add(product: product)
} else {
self.remove(product: product)
}
}
func updateCart() {
for item in self.items {
if item.quantity == 0 {
updateCart(with: item.product)
}
}
}
func add(product: Product) {
let item = items.filter { $0.product == product }
if item.first != nil {
item.first!.quantity += 1
} else {
items.append(CartItem(product: product))
}
}
func remove(product: Product) {
guard let index = items.firstIndex(where: { $0.product == product }) else { return}
items.remove(at: index)
}
func contains(product: Product) -> Bool {
let item = items.filter { $0.product == product }
return item.first != nil
}
}
I can also post “CartItemTableViewCell” and “CartViewController” if you will.
Any help would be greatly appreciated.
Edit: The original issue is resolved now, thanks to #Larme.
I have another issue for which I have pasted “CartViewController” and “CartItemTableViewCell” as well along with some rectifications in the old code after reading #Larme's first comment.
The issue is in CartViewController - When I click on Checkout button after loading the cart, it shows error in CartviewController's "tableView(_ tableView: UITableView, numberOfRowsInSection" - see CartVieController code below:-
class CartViewController
import UIKit
class CartViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var totalView: UIView!
#IBOutlet weak var totalLabel: UILabel!
var cart: Cart? = nil
fileprivate let reuseIdentifier = "CartItemCell"
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView(frame: .zero)
}
}
extension CartViewController: UITableViewDelegate, UITableViewDataSource {
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return (cart?.items.count)!// Error - Thread 1:EXC_BAD_INSTRUCTION..
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! CartItemTableViewCell
if let cartItem = cart?.items[indexPath.item] {
cell.delegate = self as CartItemDelegate
cell.nameLabel.text = cartItem.product.name
// cell.priceLabel.text = cartItem.product.price
cell.quantityLabel.text = String(describing: cartItem.quantity)
cell.quantity = cartItem.quantity
// cell.contentView.backgroundColor = !cell.decrementButton.isEnabled ? .white : .blue
}
return cell
}
}
extension CartViewController: CartItemDelegate {
// MARK: - CartItemDelegate
func updateCartItem(cell: CartItemTableViewCell, quantity: Int) {
guard let indexPath = tableView.indexPath(for: cell) else { return }
guard let cartItem = cart?.items[indexPath.row] else { return }
//Update cart item quantity
cartItem.quantity = quantity
//Update displayed cart total
// guard let total = cart?.total else { return }
//totalLabel.text = String(total)
// print(total)
}
}
class CartItemTableViewCell -
import UIKit
protocol CartItemDelegate {
func updateCartItem(cell: CartItemTableViewCell, quantity: Int)
}
class CartItemTableViewCell: UITableViewCell {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
#IBOutlet weak var incrementButton: UIButton!
#IBOutlet weak var decrementButton: UIButton!
#IBOutlet weak var quantityLabel: UILabel!
var delegate: CartItemDelegate?
var quantity: Int = 1
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
incrementButton.layer.cornerRadius = 10
incrementButton.clipsToBounds = true
decrementButton.layer.cornerRadius = 10
decrementButton.clipsToBounds = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
#IBAction func updateCartItemQuantity(_ sender: Any) {
if (sender as! UIButton).tag == 0 {
quantity = quantity + 1
} else if quantity > 0 {
quantity = quantity - 1
}
decrementButton.isEnabled = quantity > 0
decrementButton.backgroundColor = !decrementButton.isEnabled ? .gray : .black
self.quantityLabel.text = String(describing: quantity)
self.delegate?.updateCartItem(cell: self, quantity: quantity)
}
}

How to add search functionality to table view which has yelp api data?

I want to add restaurant category search functionality to RestaurantTableViewController which use yelp api business data. I followed basic search bar in table view tutorials but I do not do for my specific scenario. I do not differ filtered data and not filtered data in my RestaurantTableViewController when the search is active.
RestaurantTableViewController is below:
import UIKit
import CoreLocation
protocol ListActions: class {
func didTapCell(_ viewController: UIViewController, viewModel: RestaurantListViewModel)
}
class RestaurantTableViewController: UIViewController, UITableViewDelegate, FiltersViewControllerDelegate {
#IBOutlet weak var yourLocationLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
private let locationManager = CLLocationManager()
private let locationService = LocationService()
var filteredData: [RestaurantListViewModel]!
let appDelegate = UIApplication.shared.delegate as? AppDelegate
var viewModels = [RestaurantListViewModel]() {
didSet {
DispatchQueue.main.async {
// this no more loading, i notice it load late that is why when reload data in table view not working
}
}
}
weak var delegate: ListActions?
override func viewDidLoad() {
super.viewDidLoad()
filteredData = appDelegate!.data
userCurrentLocation()
DispatchQueue.main.async {
self.tabBarController?.tabBar.isHidden = false
}
if appDelegate?.data?.count == 0 {
tableView.setEmptyView(title: "There are no restaurants in your current location.", message: "Please change your location and try again!")
}
tableView.reloadData()
}
override func viewWillAppear(_ animated: Bool) {
if appDelegate?.data?.count == 0 {
tableView.setEmptyView(title: "There are no restaurants in your current location.", message: "Please change your location and try again!")
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("did appear")
self.removeActivityIndicator()
tableView.reloadData()
tableView.dataSource = self
tableView.delegate = self
DispatchQueue.main.async {
self.tabBarController?.tabBar.isHidden = false
}
}
}
extension RestaurantTableViewController: UITableViewDataSource {
// MARK: - Table view data source
func collectionSkeletonView(_ skeletonView: UITableView, cellIdentifierForRowAt indexPath: IndexPath) -> ReusableCellIdentifier {
return "RestaurantCell"
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("number of rows \(String(describing: viewModels.count))")
print(viewModels)
if appDelegate?.data?.count == 0 {
self.tableView.setEmptyView(title: "There are no restaurants in your current location.", message: "Please change your location and try again!")
}
if (self.searchBar.isUserInteractionEnabled) {
return self.filteredData.count
}
else {
return appDelegate!.data?.count ?? 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RestaurantCell", for: indexPath) as! RestaurantTableViewCell
if (self.searchBar.isUserInteractionEnabled) {
let vm = filteredData?[indexPath.row]
cell.configure(with: vm!)
return cell
} else {
let vm = appDelegate!.data?[indexPath.row]
cell.configure(with: vm!)
return cell
}
}
// MARK: - Delegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let detailsViewController = storyboard?.instantiateViewController(withIdentifier: "DetailsViewController")
else {return}
navigationController?.pushViewController(detailsViewController, animated: true)
let vm = appDelegate!.data?[indexPath.row]
appDelegate!.didTapCell(detailsViewController, viewModel: vm!)
if let selectedRowIndexPath = self.tableView.indexPathForSelectedRow {
self.tableView.deselectRow(at: selectedRowIndexPath, animated: true)
}
}
}
extension RestaurantTableViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredData = searchText.isEmpty ? appDelegate?.data : appDelegate?.data?.filter { (item: RestaurantListViewModel) -> Bool in
return item.categories[0].title.range(of: searchText, options: .caseInsensitive, range: nil, locale: nil) != nil
}
tableView.reloadData()
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
self.searchBar.showsCancelButton = true
}
}
My RestaurantTableViewCell data is below and I am getting restaurant table view cell data in configure function. But in RestaurantTableViewController's cellForRow method I do not differ my filtered and normal data when search is active.
class RestaurantTableViewCell: UITableViewCell {
#IBOutlet weak var cardContainerView: ShadowView!
#IBOutlet weak var restaurantImageView: UIImageView!
#IBOutlet weak var makerImageView: UIImageView!
#IBOutlet weak var restaurantNameLabel: UILabel!
#IBOutlet weak var locationLabel: UILabel!
#IBOutlet weak var restaurantType: UILabel!
let cornerRadius : CGFloat = 10.0
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
cardContainerView.layer.cornerRadius = cornerRadius
func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
cardContainerView.layer.shadowColor = UIColor.gray.cgColor
cardContainerView.layer.shadowOffset = CGSize(width: 5.0, height: 5.0)
cardContainerView.layer.shadowRadius = 15.0
cardContainerView.layer.shadowOpacity = 0.9
restaurantImageView.layer.cornerRadius = cornerRadius
restaurantImageView.clipsToBounds = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func configure(with viewModel: RestaurantListViewModel) {
// For background thread
DispatchQueue.global(qos: .background).async {
DispatchQueue.main.async {
self.restaurantImageView.af_setImage(withURL: viewModel.imageUrl)
self.restaurantNameLabel.text = viewModel.name
self.locationLabel.text = "\(viewModel.formattedDistance) m"
}
}
if let restaurantType: String = String(viewModel.categories[0].title) {
self.restaurantType.text = restaurantType
}
}
}
RestaurantListViewModel is below also:
struct Business: Codable {
let id: String
let name: String
let imageUrl: URL
let distance: Double
let categories: [Category]
}
struct RestaurantListViewModel {
let name: String
let imageUrl: URL
let distance: Double
let id: String
let categories: [Category]
}
extension RestaurantListViewModel {
init(business: Business) {
self.name = business.name
self.id = business.id
self.imageUrl = business.imageUrl
self.distance = business.distance
self.categories = business.categories
}
}

How to pass TableViewCell value into new ViewController in Swift 3.0?

I have this JSON data
move.json
{
"status":"ok",
"movement":
[
{
"refno":"REF 1",
"dtfrom":"2017-13-12"
},
{
"refno":"REF 2",
"dtfrom":"2017-13-13"
},
{
"refno":"REF 3",
"dtfrom":"2017-13-14"
},
]
}
So far, I managed to fetch the value into TableViewCell.
But my goal is to pass the value from ViewController.swift into MoveDetails.swift so the value can be display in MoveDetails.swift
And I have these four swift files. I'm having the problem on ViewController.swift and MoveDetails.swift. I'm not sure how to pass the value into new Controller.
The code as below.
ViewController.swift
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableview: UITableView!
var move: [Move]? = []
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
}
func fetchData() {
let urlRequest = URLRequest(url: URL(string: "http://localhost/move.json")!)
let task = URLSession.shared.dataTask(with: urlRequest) {
(data,response,error)in
if error != nil { return }
self.move = [Move]()
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]
if let msFromJson = json["movement"] as? [[String: AnyObject]] {
for mFromJson in msFromJson {
let ms = Move()
if let refno = mFromJson["refno"] as? String, let dtfrom = mFromJson["dtfrom"] as? String {
ms.refno = refno
ms.dtfrom = dtfrom
}
self.move?.append(ms)
}
}
DispatchQueue.main.async {
self.tableview.reloadData()
}
}
catch let error{ print(error)}
}
task.resume()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "movementstatusCell", for: indexPath) as! MoveCell
cell.refnoLbl.text = self.move?[indexPath.item].refno
cell.dtfromLbl.text = self.move?[indexPath.item].dtfrom
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.move?.count ?? 0
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "MoveDetails") as! MoveDetails
let selectedMove = self.move?[indexPath.item]
vc.refnoString = selectedMove.refno
vc.dtfromString= selectedMove.dtfrom
self.navigationController?.pushViewController(vc, animated: true)
}
}
MoveCell.swift
import UIKit
class MoveCell: UITableViewCell {
#IBOutlet weak var dtfromLbl: UILabel!
#IBOutlet weak var refnoLbl: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
Move.swift (NSObject)
import UIKit
class Move: NSObject {
var refno: String?
var dtfrom: String?
}
MoveDetails.swift
import UIKit
class MoveDetails: UIViewController {
#IBOutlet weak var refnoLbl: UILabel!
#IBOutlet weak var dtfromLbl: UILabel!
var refnoString: String!
var dtfromString: String!
override func viewDidLoad() {
super.viewDidLoad()
refnoString = refnoLbl.text
dtfromString = dtfromLbl.text
}
override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }
}
Appreciate if someone can help. Thanks.
You will just have to set the properties of your MoveDetails view controller. And as a suggestion
Instead of storing refnoString and dtfromString properties in MoveDetails, you could just store one property of type Move:
Cache MoveDetails view controller to reuse it
Implement viewDidAppear to update the MoveDetails outlets
So:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var detailsVC : MoveDetails?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if (detailsVC == nil) {
detailsVC = self.storyboard?.instantiateViewController(withIdentifier: "MoveDetails") as! MoveDetails
}
detailsVC.move = self.move?[indexPath.item]
self.navigationController?.pushViewController(detailsVC , animated: true)
}
}
Then, override viewDidAppear in MoveDetails view controller and there you just fill in the values into the text label outlets.
class MoveDetails: UIViewController {
#IBOutlet weak var refnoLbl: UILabel!
#IBOutlet weak var dtfromLbl: UILabel!
var move:Move?
override func func viewDidAppear(_ animated: Bool) {
refnoLbl.text = move?.refno
dtfromLbl.text = move?.dtfrom
}
}
Syntax errors cause because I currently have no Xcode available to do the checking

CoreData: error: Failed to call designated initializer on NSManagedObject class

I did some research and I really don't understand what happened here.
I have this error when I select a row in a table view :
Wish[1392:37721] CoreData: error: Failed to call designated initializer on NSManagedObject class 'Wish.ProduitEntity'
(lldb)
The error is on the prepareForSegue method in ViewController class.
Thanks for the help
import UIKit
import CoreData
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var leTbleView: UITableView!
var arrayProduit = [ProduitEntity]()
var produitSelectionne : ProduitEntity? = nil
override func viewDidLoad() {
super.viewDidLoad()
self.leTbleView.dataSource = self
self.leTbleView.delegate = self
}
override func viewWillAppear(animated: Bool) {
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let request = NSFetchRequest(entityName: "ProduitEntity")
var ilStock = [AnyObject]?()
do{
try ilStock = context.executeFetchRequest(request)
} catch _ {
}
//put info in the tableView
if ilStock != nil {
arrayProduit = ilStock as! [ProduitEntity]
}
self.leTbleView.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayProduit.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel!.text = (arrayProduit[indexPath.row]).nom
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
produitSelectionne = self.arrayProduit[indexPath.row]
performSegueWithIdentifier("detailSegue", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "detailSegue" {
let detailVC = segue.destinationViewController as! DetailViewController
detailVC.uneInstanceEntity = self.produitSelectionne!}
}
}
import UIKit
import CoreData
class DetailViewController: UIViewController {
#IBOutlet weak var titleLbl: UILabel!
#IBOutlet weak var storeLbl: UILabel!
#IBOutlet weak var imageProduit: UIImageView!
var uneInstanceEntity = ProduitEntity()
override func viewDidLoad() {
super.viewDidLoad()
self.titleLbl.text = uneInstanceEntity.nom
self.storeLbl.text = uneInstanceEntity.magasin
}
}
import UIKit
import CoreData
class ajouterProduitViewController: UIViewController {
#IBOutlet weak var modelTxtField: UITextField!
#IBOutlet weak var magasinTxtField: UITextField!
#IBOutlet weak var photoImage: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
//Add a new product
func sauvegardeProduit() {
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let objetEntity = NSEntityDescription.insertNewObjectForEntityForName("ProduitEntity", inManagedObjectContext: context) as!ProduitEntity
objetEntity.nom = modelTxtField.text
objetEntity.magasin = magasinTxtField.text
//objetEntity.unVisuel = UIImageJPEGRepresentation(UIImage(named: ""), 1)
do {
try context.save()
} catch _ {
}
}
#IBAction func saveBtn(sender: AnyObject) {
sauvegardeProduit()
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func cnclBtn(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
The problem is this line:
var uneInstanceEntity = ProduitEntity()
Because you're directly creating an instance. You should't do that, you should make it optional or forced:
var uneInstanceEntity: ProduitEntity!

UISearchController number of rows not getting called

I'm trying to send a request to search for movies, but when i tap on the search bar to write the text i get a crash in cellforrow and it's not calling numberofrows neither the request. Here's my code so far:
class InTheaters: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {
#IBOutlet weak var poster: UIImageView!
#IBOutlet weak var movieTitle: UILabel!
#IBOutlet weak var date: UILabel!
#IBOutlet weak var duration: UILabel!
#IBOutlet weak var rating: UILabel!
#IBOutlet var theatersTable: UITableView!
#IBOutlet weak var starsView: CosmosView!
var results = [Movie]()
var searchResults = [Search]()
var resultSearchController: UISearchController!
private let key = "qtqep7qydngcc7grk4r4hyd9"
override func viewDidLoad() {
super.viewDidLoad()
self.resultSearchController = UISearchController(searchResultsController: nil)
self.resultSearchController.searchResultsUpdater = self
self.resultSearchController.dimsBackgroundDuringPresentation = false
self.resultSearchController.searchBar.sizeToFit()
self.resultSearchController.searchBar.placeholder = "Search for movies"
self.theatersTable.tableHeaderView = self.resultSearchController.searchBar
self.theatersTable.reloadData()
getMovieInfo()
customIndicator()
infiniteScroll()
}
func customIndicator() {
self.theatersTable.infiniteScrollIndicatorView = CustomInfiniteIndicator(frame: CGRectMake(0, 0, 24, 24))
self.theatersTable.infiniteScrollIndicatorMargin = 40
}
func infiniteScroll() {
self.theatersTable.infiniteScrollIndicatorStyle = .White
self.theatersTable.addInfiniteScrollWithHandler { (scrollView) -> Void in
self.getMovieInfo()
}
}
func getMovieInfo() {
Alamofire.request(.GET, "http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json?page_limit=10&page=1&country=us&apikey=\(key)").responseJSON() {
(responseData) -> Void in
if let swiftyResponse = responseData.result.value {
let movies = Movies(JSONDecoder(swiftyResponse))
for movie in movies.allMovies {
self.results.append(movie)
}
}
self.theatersTable.reloadData()
self.theatersTable.finishInfiniteScroll()
}
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
self.searchResults.removeAll(keepCapacity: false)
if (searchController.searchBar.text?.characters.count > 0) {
Alamofire.request(.GET, "http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=N&page_limit=10&page=1&apikey=\(key)").responseJSON() {
(responseData) -> Void in
print(responseData)
if let swiftyResponse = responseData.result.value {
let searches = Searches(JSONDecoder(swiftyResponse))
for search in searches.allSearches {
self.searchResults.append(search)
}
}
self.theatersTable.reloadData()
self.theatersTable.finishInfiniteScroll()
}
}
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.resultSearchController.active) {
return self.searchResults.count
} else {
return self.results.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
let titleLabel = cell.viewWithTag(1) as! UILabel
let yearLabel = cell.viewWithTag(2) as! UILabel
let durationLabel = cell.viewWithTag(3) as! UILabel
let posterImage = cell.viewWithTag(5) as! UIImageView
let starsTag = cell.viewWithTag(6) as! CosmosView
if (self.resultSearchController.active) {
titleLabel.text = searchResults[indexPath.row].titleMovie
yearLabel.text = searchResults[indexPath.row].yearMovie
durationLabel.text = searchResults[indexPath.row].durationMovie?.description
posterImage.sd_setImageWithURL(NSURL(string: searchResults[indexPath.row].posterMovie!))
starsTag.rating = searchResults[indexPath.row].ratingMovie!
starsTag.settings.updateOnTouch = false
} else {
titleLabel.text = results[indexPath.row].titleMovie
yearLabel.text = results[indexPath.row].yearMovie
durationLabel.text = results[indexPath.row].durationMovie?.description
posterImage.sd_setImageWithURL(NSURL(string: results[indexPath.row].posterMovie!))
starsTag.rating = results[indexPath.row].ratingMovie!
starsTag.settings.updateOnTouch = false
}
return cell
}
I also have some structs with information for the request tell me if you need something from that too.
Found the answer should have reloadData before the request.
func updateSearchResultsForSearchController(searchController: UISearchController) {
self.searchResults.removeAll(keepCapacity: false)
self.theatersTable.reloadData()//should have added this before the request
if (searchController.searchBar.text?.characters.count > 0) {
Alamofire.request(.GET, "http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=\(searchController.searchBar.text!)&page_limit=10&page=1&apikey=\(key)").responseJSON() {
(responseData) -> Void in
if let swiftyResponse = responseData.result.value {
let searches = Searches(JSONDecoder(swiftyResponse))
for search in searches.allSearches {
self.searchResults.append(search)
}
}
self.theatersTable.reloadData()
self.theatersTable.finishInfiniteScroll()
}
}
}

Resources