Search code examples
swiftinheritanceprotocolssubclass

How to import or access UITextField from another Class


I have Outlet of UITextField in the main VC and I want to access its text from another class... for more clarification please see my code below:

class ProductManagement : UIViewController, UITextFieldDelegate{

    @IBOutlet weak var ProductName: UITextField!

}

and I want to read the text in below class

import Firebase
import FirebaseStorage

class XUpload {
    
    
    static func UploadImage(Image : UIImage, Completion : @escaping (_ url : String)->()) {
        
        guard let imageData = Image.pngData()  else { return }
                let storage = Storage.storage().reference()
        let pathRef = storage.child("Images/Products")
        
        let imageRef = pathRef.child(   // I want the product name to be written here!  )
        

            imageRef.putData(imageData, metadata: nil) { (meta, error) in
            imageRef.downloadURL { (url, error) in
                print (url as Any)
                                                
            }
        }
    }
    
    
    
}

I tried to create a custom protocol to delegate the UITextField but the problem is I couldn't conform it inside XUpload class !!

Please someone write for me how is my code should be because I'm beginner and new to Swift language.

Thank you in advance.

EDIT:

Elia Answer applied below:

ProductManagement Class + Extension

    class ProductManagement : UIViewController, UITextFieldDelegate{
    
    override func viewDidLoad() {
            super.viewDidLoad()
        
            self.ProductName.delegate = self
    }
    
    
        @IBOutlet weak var ProductName: UITextField!
        @objc private func textFieldDidChange(_ sender: UITextField) {
            NotificationCenter.default.post(name: .PnameInputText, object: nil, userInfo: ["text": sender.text!])
        }
    
    
    }


extension Notification.Name {
    public static var PnameInputText = Notification.Name("PnameInputText")
}

XUpload Class

import Firebase
import FirebaseStorage

class XUpload {
    
    private init() {
        NotificationCenter.default.addObserver(self, selector: #selector(handle(_:)), name: .PnameInputText, object: nil)
    }
    
    public static var shared = XUpload()
    
    var textFieldText : String = "" {
        didSet {print("updated value > ", textFieldText)}
    }
    

    @objc private func handle(_ sender: Notification) {
        if let userInfo = sender.userInfo as NSDictionary?, let text = userInfo["text"] as? String {
        textFieldText = text
        }
    }
        
    
    
    
    static func UploadImage(Image : UIImage, Completion : @escaping (_ url : String)->()) {
        
        guard let imageData = Image.pngData()  else { return }
        
        let storage = Storage.storage().reference()
        let pathRef = storage.child("Images/Products")
        let imageRef = pathRef.child("img_"+shared.textFieldText)
        print("var of textFieldText value: " + shared.textFieldText)  //print nothing... empty value!!
        
                
        imageRef.putData(imageData, metadata: nil) { (meta, error) in
            imageRef.downloadURL { (url, error) in
                print ("Image uploaded to this link >> " + url!.description)
                guard let str = url?.absoluteString else { return }
                Completion (str)
            }
        }
    }
    
}



extension UIImage {
    
    func upload(completion : @escaping (_ url : String) ->()) {
        XUpload.UploadImage(Image: self) { (ImageURL) in completion (ImageURL)
                        
        }
    }
}

As you can see there is no value given to var textFieldText by the Notification Center! why??


Solution

  • class ProductManagement : UIViewController, UITextFieldDelegate{
        var productInputText: String = ""
        @IBOutlet weak var ProductName: UITextField!
    
        override func viewDidLoad() { 
            super.viewDidLoad() 
            ProductName.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
        }
    
        @objc private func textFieldDidChange(_ sender: UITextField) {
             productInputText = sender.text ?? ""
        }
    
    }
    

    This will store your input text into a variable basically with listen edit changes.

    And if I get not wrong, you use UploadImage within ProductManagement class. Add a function property to UploadImage as below

    class XUpload {
        
        
        static func UploadImage(Image : UIImage, productName: String,  Completion : @escaping (_ url : String)->()) {
            
            guard let imageData = Image.pngData()  else { return }
                    let storage = Storage.storage().reference()
            let pathRef = storage.child("Images/Products")
            
            let imageRef = pathRef.child(   // I want the product name to be written here!  )
            
    
                imageRef.putData(imageData, metadata: nil) { (meta, error) in
                imageRef.downloadURL { (url, error) in
                    print (url as Any)
                                                    
                }
            }
        }
        
        
        
    }
    

    and call it in ProductManagement class like below.

    XUpload.UploadImage(image: myImage, productName: productInputText, Completion: { 
    
    }
    

    EDIT:

    After getting your comment, I decided the best way do it is using Notification, you use UITextField in ProductManagement class so there is no need to handle delegate method of them in XUpload

    Describe notification name

    extension Notification.Name {
        public static var TextChange = Notification.Name("TextChange")
    }
    

    In ProductManagement, textDidChange method post text to Notification

    @objc private func textFieldDidChange(_ sender: UITextField) {
            NotificationCenter.default.post(name: .TextChange, object: nil, userInfo: ["text": sender.text])
        }
    

    I convert your XUpload class to a Singleton class.

    class XUpload {
        
        private init() {
            NotificationCenter.default.addObserver(self, selector: #selector(handle(_:)), name: .TextChange, object: nil)
        }
        
        public static var Shared = XUpload()
    
        @objc private func handle(_ sender: Notification) {
            if let userInfo = sender.userInfo as NSDictionary?, let text = userInfo["text"] as? String {
                textFieldText = text
            }
            
        }
        
        var textFieldText: String = "" {
            didSet {
                print("updated value > " , textFieldText)
            }
        }
        
        static func uploadImage() {
            // use updated textfield text with textFieldText
        }
        
        
    }
    

    Then store a variable in ProductManagement class as a singleton object and it wil work for you. The text in textfield updated every changes in XUpload class.

    class ProductManagement : UIViewController, UITextFieldDelegate{
       var staticVariable = XUpload.Shared
    }