sci3nt15t
sci3nt15t

Reputation: 93

Acess uiviewController element from another class

there is this project im working on, but there is a problem with the element in the viewcontroller of my storyboard which i want to change its property from another class! my first approach was instantiating an object from the viewcontroller in my second class! which returns nil at runtime!

        func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//        let mainstampvc = MainStampVc().storyboard?.instantiateViewController(withIdentifier: "mainstampvc") as? MainStampVc
//        mainstampvc?.setstampimage(imageURL: list_images[indexPath.row])
        
        let msvc = mainstampvc()
        mainstampvc?.setstampimage(imageURL: list_images[indexPath.row])
    }

my second approache was instantiate the whole viewcontroller again in my second class which does nothing.

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let mainstampvc = MainStampVc().storyboard?.instantiateViewController(withIdentifier: "mainstampvc") as? MainStampVc
    mainstampvc?.setstampimage(imageURL: list_images[indexPath.row])
}

the whole thing i wanted is when i click on my uicollectionviewcell change the background of one of my MainViewcontroller views. here is all my classes

viewcontroller.swift

import Foundation
import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var stampholder: UIView!
    @IBAction func TextViewButton(_ sender: Any) {
        removerSubViews()
        addSubView(ViewName: "text")
    }
    @IBAction func AViewButton(_ sender: Any) {
        removerSubViews()
        addSubView(ViewName: "mohr")
    }
    @IBAction func BorderViewButton(_ sender: Any) {
    }
    @IBAction func DlViewButton(_ sender: Any) {
    }
    @IBOutlet weak var holderView: UIView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        addSubView(ViewName: "mohr")
        let mainstampvc = self.storyboard?.instantiateViewController(withIdentifier: "mainstampvc")
        let mainstampview = mainstampvc?.view
        mainstampview?.frame = stampholder.frame
        stampholder.addSubview((mainstampview)!)
    }
    func removerSubViews(){
            for view in self.holderView.subviews{
                view.removeFromSuperview()
            }
    }
    func addSubView(ViewName: String)
    {
        if let subview = Bundle.main.loadNibNamed(ViewName, owner: self, options: nil)?.first as? UIView {
            self.holderView.addSubview(subview);
        }
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

mohrcollectionview.swift

import Foundation
import UIKit

class MohrCollectionViewController: UIView,UICollectionViewDataSource,UICollectionViewDelegate{
    var mohrPath: String = ""
    var fileManager: FileManager!
    var list_images : [String] = []
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        fileManager = FileManager.default
        let currentDir = Bundle.main.resourcePath
        mohrPath = currentDir!
        let mohrsPath = try? fileManager.contentsOfDirectory(atPath: mohrPath + "/mohr")
        list_images = mohrsPath!
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
        return list_images.count
    }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        collectionView.register(UINib(nibName: "mohrcell", bundle: nil), forCellWithReuseIdentifier: "mohrcell")
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mohrcell", for: indexPath) as! mohrCellController
        let image = UIImage(named: list_images[indexPath.row])
        cell.cellimage.image = image
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let mainstampvc = MainStampVc().storyboard?.instantiateViewController(withIdentifier: "mainstampvc") as? MainStampVc
        mainstampvc?.setstampimage(imageURL: list_images[indexPath.row])
    }

}

mainstampvc.swift

import Foundation
import UIKit

class MainStampVc: UIViewController{
    

    @IBOutlet weak var stampimage: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()
        setstampimage(imageURL: "golbanafsh.png")
    }
    public func setstampimage(imageURL: String)
    {
        stampimage.image = UIImage(named: imageURL)
    }
}

any help would be appreciated

2

so here is my code with delegation but still nothing :(

//
//  MohrCollectionViewController.swift
//  Mohrem
//
//  Created by shayan rahimian on 12/18/17.
//  Copyright © 2017 shayan rahimian. All rights reserved.
//
import Foundation
import UIKit



class MohrCollectionViewController: UIView,UICollectionViewDataSource,UICollectionViewDelegate,UpdateBackgroundDelegate{
    var updatedelegate:UpdateBackgroundDelegate? = nil
    func updateBackground(imageURL: String) {
        print("mohr update back ground e balaE")
        if updatedelegate == nil {
            print("no delegate")
        }else{
            updatedelegate?.updateBackground(imageURL: imageURL)
        }
    }
    var mohrPath: String = ""
    var fileManager: FileManager!
    var list_images : [String] = []
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        fileManager = FileManager.default
        let currentDir = Bundle.main.resourcePath
        mohrPath = currentDir!
        let mohrsPath = try? fileManager.contentsOfDirectory(atPath: mohrPath + "/mohr")
        list_images = mohrsPath!
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
        return list_images.count
    }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        collectionView.register(UINib(nibName: "mohrcell", bundle: nil), forCellWithReuseIdentifier: "mohrcell")
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mohrcell", for: indexPath) as! mohrCellController
        let image = UIImage(named: list_images[indexPath.row])
        cell.cellimage.image = image
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        self.updateBackground(imageURL: list_images[indexPath.row])
    }
    
}



//
//  MainStampvc.swift
//  Mohrem
//
//  Created by shayan rahimian on 12/19/17.
//  Copyright © 2017 shayan rahimian. All rights reserved.
//

import Foundation
import UIKit

protocol UpdateBackgroundDelegate : class {
    func updateBackground(imageURL: String)
}
class MainStampVc: UIViewController{

    @IBOutlet weak var stampimage: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()
        updateBackground(imageURL: "biggolabi.png")
        
    }
    func updateBackground(imageURL: String) {
        // update your background in this funcion
        print("extension")
        print(imageURL)
        stampimage.image = UIImage(named: imageURL)
    }

}

am i doing anything wrong?

Upvotes: 0

Views: 695

Answers (2)

manish_kumar
manish_kumar

Reputation: 260

For making the delegate work do the following:

  1. Declare the delegate first like in Collection View Class

    protocol UpdateBackgroundDelegate : class {
    func updateBackground(imageURL: String)
    }
    
  2. Create a variable like

    var updateDelegate: UpdateBackgroundDelegate?
    

and paste it below your collectionView class from where you want to trigger changing background colour

  1. In the collection view selection delegate, add this line of code

    updateDelegate.updateBackground(imageUrl: yourUrl) 
    
  2. In the View, where colour change has to take place, create your collectionView instance and add this line of code

    collectionView.updateDelegate = self 
    
  3. At last add this extension

    class ViewController :UpdateBackgroundDelegate {
       func updateBackground(imageUrl: yourUrl) {
          //write code to load image from url
       }
    }
    

Upvotes: 0

adamfowlerphoto
adamfowlerphoto

Reputation: 2751

You could pass a UIViewController reference to the MohrCollectionViewController(you should call this MohrCollectionView to avoid confusion) at the time you construct it. Then whenever you need to update the background you call the relevant function on the reference.

class ViewController : UIViewController {
    ...
    override func viewDidLoad() {
        ...
        let view = addSubView(ViewName: "mohr")
        view?.vc = self
    }
    func addSubView(ViewName: String) -> UIView?
    {
        if let subview = Bundle.main.loadNibNamed(ViewName, owner: self, options: nil)?.first as? UIView {
            self.holderView.addSubview(subview);
            return subview
        }
    }
    return nil
}

class MohrCollectionView {

     func updateVcBackground() {
         vc?.updateBackground()
     }
     var vc : ViewController? = nil
}

A cleaner way to do this is use a delegate. A delegate uses a protocol to define an interface between two classes.

protocol UpdateBackgroundDelegate : class {
    func updateBackground()
}

class ViewController : UIViewController, UpdateBackgroundDelegate {
    ...
    override func viewDidLoad() {
        ...
        let view = addSubView(ViewName: "mohr")
        view?.updateBackgroundDelegate = self
    }
    func updateBackground() {
        // update your background in this funcion
    }
}

class MohrCollectionView {

     func updateVcBackground() {
         updateBackgroundDelegate?.updateBackground()
     }
     var updateBackgroundDelegate : UpdateBackgroundDelegate? = nil
}

Upvotes: 1

Related Questions