UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Day 50 - Milestone challenge FIXED

Forums > 100 Days of Swift

Update: I fixed this : )

Hello my friends,

I am so close to figuring out the Milestone challange but running into 2 bugs that i just can't figure out :

  1. After taking the photo, an alert window will pop up with textfield for me to add captions. However this alert window keeps popping out even after I have added the text, and will not go away unless i select "cancel".

  2. I can't get the Image to show in my detailViewController. In the detailViewController, there is the Title, which should be the same as whatever captions i added to the photo previously, and then the image itself. The title is showing up fine, but nothing in the ImageView.

PS: The class i created is called " EachCell ", which contains var Caption, and var Photo.

My ViewController:

class ViewController: UITableViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    var pictures = [eachCell]()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(takePhoto))
    }

    @objc func takePhoto() {
        let picker = UIImagePickerController()
        //        picker.sourceType = .camera
        picker.allowsEditing = true
        picker.delegate = self
        present(picker, animated: true)
    }

    /*Extract the image from the dictionary that is passed as a parameter.
     Generate a unique filename for it.
     Convert it to a JPEG, then write that JPEG to disk.
     Dismiss the view controller.*/
    func getDocumentsDirectory() -> URL {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return paths[0]
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        guard let image = info[.editedImage] as? UIImage else{return}

        let imageName = UUID().uuidString
        let imagePath = getDocumentsDirectory().appendingPathComponent(imageName)

        if let jpegData = image.jpegData(compressionQuality: 0.8){
            try? jpegData.write(to: imagePath)
        }

        let newCell = eachCell(caption: "Caption: ", photo: imageName)
        pictures.append(newCell)

        tableView.reloadData()

        dismiss(animated: true)
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return pictures.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        guard let rows = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? CaptionedPhoto else{
            fatalError("something went wrong with deque")
        }

        let person = pictures[indexPath.row]
        let path = getDocumentsDirectory().appendingPathComponent(person.photo)
        rows.imageView?.image = UIImage(contentsOfFile: path.path)

        //either go here
//        rows.caption.text = person.caption

        let ac = UIAlertController(title: "Add captions to this photo", message: nil, preferredStyle: .alert)
        ac.addTextField()

        ac.addAction(UIAlertAction(title: "cancel", style: .cancel))
        ac.addAction(UIAlertAction(title: "add", style: .default) {[weak self, weak ac] _ in
            guard let newLabel = ac?.textFields?[0].text else{ return }
            person.caption = newLabel
            self?.tableView.reloadData()
        }

        )
        present(ac, animated: true)

        rows.caption.text = person.caption
        return rows
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        if let vc = storyboard?.instantiateViewController(withIdentifier: "detail") as? DetailViewController{
            let person = pictures[indexPath.row]
            vc.selectedImage = person.photo
            vc.photoTitle = person.caption
            navigationController?.pushViewController(vc, animated: true)

        }
    }
}

My DetailViewController:

class DetailViewController: UIViewController {

    @IBOutlet var detailPhoto: UIImageView!

    var selectedImage: String?
    var photoTitle: String?

    override func viewDidLoad() {
        super.viewDidLoad()

        title = photoTitle

        if let imageToLoad = selectedImage {
            detailPhoto.image = UIImage(named: imageToLoad)
        } else {
            print("unable to pull image")
        }

        // Do any additional setup after loading the view.
    }

Grateful for your help! Thank you all !

3      

You cannot create the alert in the cellForRowAt method because you have almost no control over how often it is called and since you are calling reloadData on the table view that means cellForRowAt will get called again and that is why you are seeing the alert over and over

4      

What about func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any])?

4      

Hmm oopsss I think I accidentally deleted my previous reply??!

You are right that totally worked !!! Now i just have to figure out why my detailVC isn't showing the photo.

its loading the title fine, which is the same as caption, but no pictures. So strange. i thought it messed up the IBOutlet or something in the storyBoard , but re-did it 3 times and now im convinced my code is fked* .

Thank for your help : )

3      

Hey @teekachu How did you solve it? My pics still don't show up in the Detail view

3      

@Kru178 - For me, I think the issue was in my didSelectRowAt. I end up finding the path for where each photo were saved in the local user directory, and then used that to set my vc.selectedImage.


 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        if let vc = storyboard?.instantiateViewController(withIdentifier: "detail") as? DetailViewController{

            let path = getDocumentsDirectory().appendingPathComponent(pictures[indexPath.row].photo)
            vc.selectedImage = path.path
            vc.photoTitle = pictures[indexPath.row].caption
            navigationController?.pushViewController(vc, animated: true)

        }
    }

Here is the github code, I hope it helps? I'm obvisouly not an expert haha but this worked for me.

https://github.com/teekachu/100DaysOfSwift/blob/master/Cons_Project%234/Cons_Project%20%23%2010-12/ViewController.swift

4      

@fsafddg Ahh sorry friend, I am not familiar with Wordpress, so I couln't answer that question :(

3      

For anybody else looking for the answer why detail VC doesn't show the image after app relaunch, this article helped me: https://handyopinion.com/save-load-image-from-documents-directory-in-swift/

3      

Hacking with Swift is sponsored by Superwall

SPONSORED Superwall lets you build & test paywalls without shipping updates. Run experiments, offer sales, segment users, update locked features and more at the click of button. Best part? It's FREE for up to 250 conversions / mo and the Superwall team builds out 100% custom paywalls – free of charge.

Learn More

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.