collectionView height not set According to content Height

73 views Asked by At

how to use two collectionview inside one ViewController with UiCollectionView Height set two fixed height and may varied according to content size ? BY using NSLayoutConstraint in UIKit.please help me on this.when I try to add cell after the spacing get added with contentSize and it detect double size of what height should be. And that where problem Occurs I was expecting size should get for 4th cell is 200 but its get 410 size


you can see what response look Like it taking more space than it should take here

here we can see I have two collection under single controller embedded in scrollview

import PhotosUI
import UIKit

class SellContractController: UIViewController, UITextViewDelegate, PHPickerViewControllerDelegate,SendSpeciality,SendPackages {
    
    func sendPackage(data: [ContractPackage]) {
        print(data)
        self.itemPackages = data
        contractPackagesCollectionView.reloadData()
    }
    
    
    func sendSpeciality(data: [String]) {
        self.tagsArray = data
        specialityCollectionView.reloadData()
 }
    
    @IBOutlet weak var specialityCollectionViewHeight: NSLayoutConstraint!
    @IBOutlet weak var parentView: UIView!
    @IBOutlet weak var imageContainerView: UIView!
    @IBOutlet weak var specialityView: UIView!
    @IBOutlet weak var productTitle: UITextField!
    @IBOutlet weak var descriptionTextView: UITextView!
    @IBOutlet weak var productName: UITextField!
    @IBOutlet weak var addSpeciality: UIButton!
    @IBOutlet weak var brandname: UITextField!
    @IBOutlet weak var addPackages: UIButton!
    @IBOutlet weak var imageCollectionView: UICollectionView!
    @IBOutlet weak var contractPackagesView: UIView!
    @IBOutlet weak var sellContractButton: UIButton!
    @IBOutlet weak var specialityCollectionView: UICollectionView!
    @IBOutlet weak var contractPackagesCollectionView: UICollectionView!
    
    var sellContractItems:SellContractDetails?
    var imageArray = [UIImage] ()
    var tagsArray = [String]()
    var itemPackages = [ContractPackage]()
    var sellContractItem:SellContractDetails?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        DescriptionBorder(txtView: descriptionTextView)
        viewBorder(view: specialityView)
        viewBorder(view: imageContainerView)
        viewBorder(view: contractPackagesView)
        sellContractButton.layer.cornerRadius = 10
    }
    
  
    
    
    func DescriptionBorder(txtView:UITextView){
        descriptionTextView.text = "Product Description"
        txtView.delegate = self    // Give TextViewMessage delegate Method
        txtView.layer.borderColor = UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1.0).cgColor
        txtView.layer.borderWidth = 1.0
        txtView.layer.cornerRadius = 5
        
    }
    func viewBorder(view:UIView){
        view.layer.cornerRadius = 10
        view.layer.borderColor = UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1.0).cgColor
        view.layer.borderWidth = 1.0
        view.layer.masksToBounds = true
    }
    
    @IBAction func DoneClicked(_ sender: UIBarButtonItem) {
        sellContract()
    }
    
    @IBAction func onCreateClicked(_ sender: UIButton) {
        sellContract()
    }
    @IBAction func addPhotosClicked(_ sender: UIButton) {
        askPermission()
        openGallery()
        
    }
    func addBorder(txtfield:UITextField) {
        
        txtfield.layer.cornerRadius=15
        txtfield.layer.borderWidth = 2.0
        txtfield.layer.borderColor = #colorLiteral(red: 0.4549019608, green: 0.768627451, blue: 0.6862745098, alpha: 1)
        txtfield.layer.masksToBounds = true
        txtfield.leftViewMode = .always
        
    }
    
    @IBAction func addPackages(_ sender: UIButton) {
        self.performSegue(withIdentifier: "ContractPackageSegue", sender: self)
    }
    @IBAction func addSpeciality(_ sender: UIButton) {
        self.performSegue(withIdentifier: "SpecialitySegue", sender: self)
    }
    func openGallery(){
        
        var config = PHPickerConfiguration()
        config.selectionLimit = 5
        config.filter = .images
        let picker = PHPickerViewController(configuration: config)
        picker.delegate = self
        
        present(picker, animated: true)
    }
    
    func askPermission()
    {
        PHPhotoLibrary.requestAuthorization({(status) in
            if status == PHAuthorizationStatus.authorized
            {
                DispatchQueue.main.async{
                    
                }
            }
            else {
                print("NO access")
            }
            
        })
    }
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "SpecialitySegue"{
            let secondvc = segue.destination as! SpecialityPopup
            secondvc.tagsArray = self.tagsArray
            secondvc.speciality = self
        }
        else if segue.identifier == "ContractPackageSegue"{
            let secondvc = segue.destination as! ContractPackagesController
            secondvc.itemPackages = self.itemPackages
            secondvc.itempackage = self
        }
    }
    func textViewDidBeginEditing(_ textView: UITextView) {
        if textView == descriptionTextView {
            if !descriptionTextView.text!.isEmpty && descriptionTextView.text! == "Product Description" {
                descriptionTextView.text = ""
                descriptionTextView.textColor = UIColor.black
            }
        }
    }
    
    func textViewDidEndEditing(_ textView: UITextView) {
        if textView == descriptionTextView {
            if descriptionTextView.text.isEmpty {
                descriptionTextView.text = "Product Description"
                descriptionTextView.textColor = UIColor.lightGray
            }
        }
    }
    
    func sellContract(){
        
        var authToken = ""
        TokenService().getOrGenerateToken() { result in
            switch result {
            case .success(let token):
                authToken = token
            case .failure(_):
                DispatchQueue.main.async {
                    CustomToast.showFailure(message: "Something went wrong",  controller: self)
                }
            }
        }
        
        guard let title = self.productTitle.text, title != ""  else {
            CustomToast.show(message: "please enter Title", bgColor: .black, textColor: .red, labelFont: .systemFont(ofSize: 12.0), showIn: .bottom, controller: self)
            return
        }
        guard let brand = self.brandname.text, brand != ""  else {
            CustomToast.show(message: "please enter brand name", bgColor: .black, textColor: .red, labelFont: .systemFont(ofSize: 12.0), showIn: .bottom, controller: self)
            return
        }
        guard let product = self.productName.text, product != ""  else {
            CustomToast.show(message: "please enter product name", bgColor: .black, textColor: .red, labelFont: .systemFont(ofSize: 12.0), showIn: .bottom, controller: self)
            return
        }
        guard let description = self.descriptionTextView.text, description != ""  else {
            CustomToast.show(message: "please enter description", bgColor: .black, textColor: .red, labelFont: .systemFont(ofSize: 12.0), showIn: .bottom, controller: self)
            return
        }
        
        struct Suitability:Codable{
            let suitableFor: String
        }
        
        var suitabilities = [Suitability]()
        
        tagsArray.forEach{ tag in
            suitabilities.append(Suitability(suitableFor:tag))
        }
        
        struct UploadData: Codable {
            let itemType: String
            let title: String
            let brand:String
            let product:String
            let description : String
            let itemSuitabilities: [Suitability]?
            let itemPackages:[ContractPackage]?
        }
        
        // Add data to the model
        let uploadDataModel = UploadData(itemType:"CONTRACT",
                                         title:title,
                                         brand: brand,
                                         product: product,
                                         description: description,
                                         itemSuitabilities:  suitabilities,
                                         itemPackages: self.itemPackages
        )
        
        
        // Convert model to JSON data
        guard let jsonData = try? JSONEncoder().encode(uploadDataModel) else {
            DispatchQueue.main.async {
                CustomToast.showFailure(message: "Something went wrong", controller: self)
            }
            return
        }
        
        // Create the url request
        let postUrl = BASE_URL + "items"
        let escapedExistUrl = postUrl.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)!
        let url = URL(string: escapedExistUrl)
        var request = URLRequest(url: url!)
        
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type") // the request is JSON
        request.setValue("application/json", forHTTPHeaderField: "Accept") // the response expected to be in JSON format
        request.setValue( "Bearer \(authToken)", forHTTPHeaderField: "Authorization")
        request.httpBody = jsonData
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            guard error == nil else {
                DispatchQueue.main.async {
                    CustomToast.showFailure(message: "Something went wrong",  controller: self)
                }
                return
            }
            guard let data = data else {
                DispatchQueue.main.async {
                    CustomToast.showFailure(message: "Something went wrong",  controller: self)
                }
                return
            }
            
            
            let response = response as? HTTPURLResponse
            print(response!)
            if (200 == response?.statusCode){
                if let json = String(data: data, encoding: .utf8) {
                    print("json", json)
                }
                
                do{
                    let payload = try JSONDecoder().decode(SellContractDetails.self,from: data)
                    self.sellContractItem = payload
                    print(self.sellContractItem!)
                    if (self.imageArray.count != 0){
                        self.uploadImage(images:self.imageArray,id:self.sellContractItem!.id)
                    }
                }
                catch{
                    DispatchQueue.main.async {
                        print(error)
                        CustomToast.showFailure(message: "Something went wrong", controller: self)
                    }
                    return
                }
            }
            else  {
                DispatchQueue.main.async {
                    CustomToast.showFailure(message: "Something went wrong", controller: self)
                }
                return
            }
        }.resume()
    }

    func uploadImage(images: [UIImage],id:String) {
        var authToken = ""
        TokenService().getOrGenerateToken() { result in
            switch result {
            case .success(let token):
                authToken = token
            case .failure(_):
                DispatchQueue.main.async {
                    CustomToast.showFailure(message: "Something went wrong",  controller: self)
                }
            }
        }
        
        let boundary = UUID().uuidString
        let postUrl = BASE_URL + "items/upload-image/"+id+""
        print(postUrl)
        let escapedExistUrl = postUrl.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)!
        let url = URL(string: escapedExistUrl)
        let session = URLSession.shared
        // Set the URLRequest to POST and to the specified URL
        var urlRequest = URLRequest(url: url!)
        urlRequest.httpMethod = "POST"
        // Set Content-Type Header to multipart/form-data, this is equivalent to submitting form data with file upload in a web browser
        // And the boundary is also set here
        urlRequest.setValue( "Bearer \(authToken)", forHTTPHeaderField: "Authorization")
        urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
  
        var data = Data()
        for image in images {
            //            let fileName = String(Int64(NSDate().timeIntervalSince1970*1000)) + ".jpg"
            // Add the image data to the raw http request data
            data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
            data.append("Content-Disposition: form-data; name=\"images\"; filename=\"\(Int64(NSDate().timeIntervalSince1970*1000)).jpg\"\r\n".data(using: .utf8)!)
            data.append("Content-Type: img/png\r\n\r\n".data(using: .utf8)!)
            data.append(image.pngData()!)
            data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
        }
        // Send a POST request to the URL, with the data we created earlier
        session.uploadTask(with: urlRequest, from: data, completionHandler: { data, response, error in
            guard error == nil else {
                DispatchQueue.main.async {
                    CustomToast.showFailure(message: "Something went wrong,312", controller: self)
                }
                return
            }
            guard let data = data else {
                DispatchQueue.main.async {
                    CustomToast.showFailure(message: "Something went wrong,line 318", controller: self)
                }
                return
            }
            
            
            let response = response as? HTTPURLResponse
            
            if (200 == response?.statusCode){
                
                if let json = String(data: data, encoding: .utf8) {
                    print("json,line 329", json)
                }
                DispatchQueue.main.async {
                    CustomToast.showSuccess(message:"Image uploaded Successfully", controller: self)
                }
            }
            else {
                print(error!)
                DispatchQueue.main.async {
                    CustomToast.showFailure(message:"Something went wrong,line 337", controller: self)
                }
                
                return
            }
        }).resume()
    }
}
extension SellContractController:UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout
{
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if collectionView == specialityCollectionView{
            return tagsArray.count
        }
        else if collectionView == contractPackagesCollectionView{
            return itemPackages.count
        }
        print(imageArray.count)
        return imageArray.count
    }
    
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult])
    {
        dismiss(animated: true)
        for result in results{
            result.itemProvider.loadObject(ofClass: UIImage.self){ object,error in
                if let image = object as? UIImage{
                    self.imageArray.append(image)
                }
                DispatchQueue.main.async {
                    self.imageCollectionView.reloadData()
                }
            }
        }
        
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        if collectionView == specialityCollectionView{
            let  cell=specialityCollectionView.dequeueReusableCell(withReuseIdentifier: "MemberCell", for: indexPath) as! AddTagCollectionViewCell
            
            cell.MName.text = tagsArray[indexPath.row]
            cell.DeleteMember?.tag = indexPath.row
            cell.DeleteMember?.addTarget(self, action: #selector(deleteTag(sender:)), for: UIControl.Event.touchUpInside)

            return cell
        }
        else if collectionView == contractPackagesCollectionView{
            let  cell=contractPackagesCollectionView.dequeueReusableCell(withReuseIdentifier: "ContractPackage", for: indexPath) as! ContractPackagesCollectionViewCell
            cell.packageName.text = itemPackages[indexPath.row].packageName
            cell.priceandTerm.text = itemPackages[indexPath.row].contractTerm + "|" + String(itemPackages[indexPath.row].duration) + "|" + String(itemPackages[indexPath.row].price)
            cell.deletePackage?.tag  = indexPath.row
            cell.deletePackage?.addTarget(self, action: #selector(deletePackage(sender:)), for: UIControl.Event.touchUpInside)
         
            
            return cell
        }
        let cell=imageCollectionView.dequeueReusableCell(withReuseIdentifier:"ImageCell", for: indexPath) as! ProductImages
        cell.productImage.image = imageArray[indexPath.row]
        cell.deleteImage?.tag =  indexPath.row
        cell.deleteImage?.addTarget(self, action: #selector(deleteImage(sender:)), for: UIControl.Event.touchUpInside)
        cell.productImage.layer.cornerRadius = 10
        cell.productImage.layer.borderColor = UIColor(red: 0.9, green: 0.9, blue: 0.9, alpha: 1.0).cgColor
        cell.productImage.layer.borderWidth = 1.0
        
        return cell
    }
    
    /* delete Images */
    @objc func deleteImage(sender:UIButton) {
        let i = sender.tag
        imageArray.remove(at: i)
        imageCollectionView.reloadData()
    }
    /* delete Tags*/
    @objc func deleteTag(sender:UIButton) {
        let i = sender.tag
        tagsArray.remove(at: i)
        specialityCollectionView.reloadData()
    }
    @objc func deletePackage(sender:UIButton) {
        let i = sender.tag
        itemPackages.remove(at: i)
        contractPackagesCollectionView.reloadData()
    }
    
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 10
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 0
        
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if collectionView == specialityCollectionView
        {
            specialityCollectionViewHeight.constant = self.specialityCollectionView.collectionViewLayout.collectionViewContentSize.height
//            print(specialityCollectionViewHeight.constant)
            print(collectionView.frame.height)
            return CGSize(width: (collectionView.frame.width-10), height:specialityCollectionViewHeight.constant)
        }
        else if collectionView == contractPackagesCollectionView{
            return CGSize(width: collectionView.frame.width-10, height: collectionView.frame.height)
        }
        return CGSize(width: (collectionView.frame.width-10)/3, height: collectionView.frame.height/2)
    }
}

I Was expecting the size 210 but getting 410

0

There are 0 answers