0

I am building an iOS application for my year 12 project and it entails users being able to record information about a bill they have received and having the ability to take a photo of the bill and to save it. I have used core data for my users data to be saved to. I have currently been able to get the photo taken by the user to be able to be seen on a seperate screen when the user selects a bill. Where I am having trouble is that the YouTube video I used has only shown me how to display only 1 specific photo in position zero, as shown on line 39. I need help in getting a different image being displayed dependent on what bill the user selects. For example, if a user taps a water bill, on the viewing screen, they will see a water bill. Then if the user taps a gas bill, on the viewing screen, they will see the gas bill. Currently, what is happening is regardless of whether the user selects the gas or water bill, a water bill is displayed. I have tried to explain this the best I can, if there are any other concerns, please let me know.

Thank you for your assistance

import UIKit
import CoreData
class ViewControllerViewing: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        // Getting keyboard to retract
    }
    func fetchImage() -> [Bravo] {
        var fetchingImage = [Bravo]()
        let fetchRequest = NSFetchRequest<Bravo>(entityName: "Bravo")
        do {
            fetchingImage = try context.fetch(fetchRequest)
        } catch {
            print("Error while fetching the image")
        }
        return fetchingImage
    }
    // Outlets
    
    @IBOutlet weak var imgDisplay: UIImageView!
    var selectedImage: String?
    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

    @IBOutlet weak var lblBill: UILabel!
    // Actions
    @IBAction func btnDisplay(_ sender: Any) {
        let arr = DataBaseHelper.shareInstance.getAllImages()
        // Got to get the numbered one change dependent on what bill is pressed
        self.imgDisplay.image = UIImage(data: arr[0].photo!) // Only position zero photo displays
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
       self.view.endEditing(true)
   }

// Screen before photo screen

Class CarViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // Return the number bills
        return bills.count
    }
    // Editing function
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // Selected Person
        let bravo = self.bills[indexPath.row]
        
        // Create alert
        let alert = UIAlertController(title: "Edit Bill", message: "Edit Provider", preferredStyle: .alert)
        alert.addTextField()
        // Edit text feild to edit provider
        let txtProvider = alert.textFields![0]
        // Configure button handler
        let saveButton = UIAlertAction(title: "Save", style: .default) {
            (action) in
            // Edit provider property
            bravo.provider = txtProvider.text
            // Save new data
            do {
                try self.context.save()
            }
            catch {
                
            }
            // Refetch data
            self.fetchBravo()
        }
        // Add button
        alert.addAction(saveButton)
        // Show alert
        self.present(alert, animated: true, completion: nil)
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //ensure the cell identifier has been labelled "cell"
      //  let bravob = self.bills[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        // Recieves information from core data
        let display = self.bills[indexPath.row]
        // Displays the provider in the title
        cell.textLabel?.text = display.provider
        // Displays the date in the subtitle
        cell.detailTextLabel?.text = display.date
        //How to add photo into tableview research
        return cell
    }
    func fetchBravo() {
        // Fetch data from core data to display in a tableview
        do {
            let request = Bravo.fetchRequest() as NSFetchRequest<Bravo>
            
            //  Set the filtering and sorting on the request This is the sorting method (For setting car filter, try to adjust here) Look at predecite https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Predicates/AdditionalChapters/Introduction.html
           let pred = NSPredicate(format: "category CONTAINS '0'")
          request.predicate = pred
            self.bills = try context.fetch(request)
            
            // Sort descripter
            let sort = NSSortDescriptor(key: "provider", ascending: true)
            request.sortDescriptors = [sort]
            DispatchQueue.main.async {
                self.tblCar.reloadData()
            }
        }
        catch {
            
        }
    }
    // Swipe to delete function https://www.youtube.com/watch?v=gWurhFqTsPU&list=RDCMUC2D6eRvCeMtcF5OGHf1-trw&start_radio=1
    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        // Create swipe action
        let action = UIContextualAction(style: .destructive, title: "Delete") { (action, view, completionHandler) in
            // Which bill to removes
            let BravoRemove = self.bills[indexPath.row]
            // Remove Bill
            self.context.delete(BravoRemove)
            // Save updated delete
            do {
                try self.context.save()
            }
            catch{
                
            }
            // Refetch new data
            self.fetchBravo()
        }
        // Return swipe action
        return UISwipeActionsConfiguration(actions: [action])
    }
    
    
    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    var bills:[Bravo] = []
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tblCar.delegate = self
        tblCar.dataSource = self
        tblCar.reloadData()
        
        // Do any additional setup after loading the view.
    }

    // Outlets
    @IBOutlet weak var txtDate: UITextField!
    @IBOutlet weak var txtBill: UITextField!
    @IBOutlet weak var tblCar: UITableView!
    @IBOutlet weak var segCategory: UISegmentedControl!
    // Actions
    @IBAction func btnSearch(_ sender: Any) {
        // Re-Fetch data for core data
        self.fetchBravo()
        print(bills)
        tblCar.reloadData()
    }
Paulw11
  • 108,386
  • 14
  • 159
  • 186
JG2022
  • 21
  • 3
  • As your comment shows, you know that you are only displaying the first image because you are accessing only the first element of the array. How is your app structured? Normally you would use a tableview or a collection view to list all of the items (bills) and when a user selects one you would show another view controller with the detail of that. Xcode has a master-detail view project template for exactly this type of app. – Paulw11 Jul 22 '22 at 21:44
  • Yes, that's how my app works. My bills are displayed in a tableview and when one of the cells is selected, it goes to another page where the image is displayed. How do I access the "master-detail view" of my project? Thank you for your assistance Paulw11 – JG2022 Jul 22 '22 at 23:19
  • There isn't a master-detail view unless you have set your app up to use one. https://www.raywenderlich.com/4613809-uisplitviewcontroller-tutorial-getting-started You don't have to use one, it can just make things a bit easier for you. You need to pass the core data object from your first view controller to your second. You should put even need to fetch from core data in your detail view. You will already have the object. Show the code where your table view shows the detail view. – Paulw11 Jul 22 '22 at 23:29
  • Ah ok, that makes sense. How do I pass the core data object from my first view controller to my second one where the image appears? Thank you – JG2022 Jul 22 '22 at 23:37
  • It depends on how you are presenting the detail view controller. If you are using storyboards and segues then you would set a property on your destination view controller in `prepare(for segue:)` – Paulw11 Jul 22 '22 at 23:42
  • I have used a segue and I am using a view-controller. Do I need to use a detail view controller and if so what's the difference between a detail view controller and a normal view-controller? – JG2022 Jul 22 '22 at 23:44
  • A detail view controller is just a generic term for a view controller that shows details. It is a common term in iOS development. You don't need to use a split view controller. It can handle some of the navigation for you and also adapts automatically for layout on iPhone and iPad. What you will want to do is create a property of type `Bravo` in your `ViewControllerViewing` and set its value in `prepare(for segue:)`. [edit] your question to show your table view controller and I can probably help – Paulw11 Jul 22 '22 at 23:50
  • Ok, I have just added all the code from the page that has the tableview that shows my bills. Thank you for your help, I really appreciate it! – JG2022 Jul 23 '22 at 00:04
  • I don't see where that code displays your photo. Do you have a segue in your storyboard from the cell? – Paulw11 Jul 23 '22 at 00:33
  • Yes, I have a segue called viewSegue. The part that displays the photo is in the screen when the cell is tapped. The section is: let arr = DataBaseHelper.shareInstance.getAllImages() self.imgDisplay.image = UIImage(data: arr[0].photo!) – JG2022 Jul 23 '22 at 03:29
  • Then you need to implement `prepare(for segue:)` so that you can pass the property https://stackoverflow.com/questions/5210535/passing-data-between-view-controllers/9736559#9736559 – Paulw11 Jul 23 '22 at 05:04

0 Answers0