2017-06-17 54 views
0

我用頭撞牆,出現以下問題:我有一個顯示場地列表的UICollectionView。用戶可以選擇按地點名稱或城市進行搜索。搜索工作完美無缺,但是當UICollectionView重新加載新搜索結果時,新項目會粘貼到舊項目上。奇怪的部分是,UICollectionView似乎被清除,因爲除了第一個項目外,其他所有項目都被刪除。見我的圖片如下:UICollectionView項目未正確清除,重新粘貼的項目粘貼在舊項目上

圖片1:沒有搜索尚未啓動......

enter image description here

圖片2:優先搜索發起...

enter image description here

圖片3:第二搜索發起...顯示在其他場地上的新場地文字

enter image description here

圖片4:回到默認...文本仍然顯示在其他文本

enter image description here

下面是我的代碼檢索場館:

func loadVenuesBasedOnSearch(searchString: String) { 
     // Retrieve server URL 
     let serverUrl = DBConnection().returnConnectionUrl() 

     // Send HTTP GET Request 

     // Define server side script URL 
     let scriptUrl = serverUrl + "bmc_api.php" 

     // Add one parameter just to avoid caching 
     let urlWithParams = scriptUrl + "?request=retrieveVenuesBySearch&searchString=\(searchString)&province=" 

     // Create NSURL Object 
     let myUrl = URL(string: urlWithParams + province!.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!); 

     // Creaste URL Request 
     var request = URLRequest(url:myUrl!) 

     // Set request HTTP method to GET. It could be POST as well 
     request.httpMethod = "GET" 


     // Excute HTTP Request 
     let task = URLSession.shared.dataTask(with: request) { 
      data, response, error in 

      // Check for error 
      if error != nil 
      { 
       self.noVenues.layer.zPosition = 1 
       self.noVenues.isHidden = false 
       return 
      } 

      // Convert server json response to NSDictionary 
      do { 
       if let convertedJsonIntoArray = try JSONSerialization.jsonObject(with: data!, options: []) as? NSArray { 

        self.venues = convertedJsonIntoArray as [AnyObject] 
        let activityViewController = ActivityViewController(message: "Retrieving Venues...") 

        DispatchQueue.main.async { [unowned self] in 
         self.present(activityViewController, animated: true, completion: nil) 
         self.myCollectionView!.reloadData() 
        } 

        DispatchQueue.main.asyncAfter(deadline: .now() + 1) { 
         activityViewController.dismiss(animated: true, completion: nil) 
        } 
       } 
      } catch _ as NSError { 
       self.noVenues.layer.zPosition = 1 
       self.noVenues.isHidden = false 
      } 
     } 

     task.resume() 

    } 

,並顯示代碼項目:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
     let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath as IndexPath) 

     //Customize Collection View Cell 
     myCell.backgroundColor = UIColor(red: 64/255, green: 64/255, blue: 64/255, alpha: 1.0) 
     myCell.layer.shadowColor = UIColor.black.cgColor 
     myCell.layer.shadowOffset = CGSize(width: 4, height: 4) 
     myCell.layer.shadowOpacity = 0.3 
     myCell.layer.shadowRadius = 2.0 
     myCell.clipsToBounds = false 
     myCell.layer.masksToBounds = false 

     //Retrieve string values from Json Object 
     let venueDictionary = self.venues[indexPath.row] as! NSDictionary 
     let imageUrlString = venueDictionary.object(forKey: "venue_logo") as! String 
     let venueName = venueDictionary.object(forKey: "venue_name") as! String 
     let venueLocation = venueDictionary.object(forKey: "venue_location") as! String 
     let imageUrl:NSURL = NSURL(string: imageUrlString)! 

     DispatchQueue.global(qos: .userInitiated).async { 

      let imageData:NSData = NSData(contentsOf: imageUrl as URL)! 
      let imageView = UIImageView(frame: CGRect(x: 5, y: 5, width: myCell.frame.size.width - 10, height: myCell.frame.size.height - 60)) 
      let textVenueName = UILabel(frame: CGRect(x: 10, y: 85, width:myCell.frame.size.width, height: myCell.frame.size.height)) 
      let textVenueLocation = UILabel(frame: CGRect(x: 10, y: 110, width:myCell.frame.size.width, height: myCell.frame.size.height)) 

      DispatchQueue.main.async { 

       let image = UIImage(data: imageData as Data) 
       imageView.image = image 
       imageView.contentMode = UIViewContentMode.scaleToFill 

       textVenueName.text = venueName 
       textVenueName.textColor = UIColor.white 
       textVenueName.font = UIFont.boldSystemFont(ofSize: 16.0) 

       textVenueLocation.text = venueLocation 
       textVenueLocation.textColor = UIColor.white 
       textVenueLocation.font = UIFont.boldSystemFont(ofSize: 12.0) 

       myCell.addSubview(imageView) 
       myCell.addSubview(textVenueName) 
       myCell.addSubview(textVenueLocation) 
      } 
     } 

     return myCell 
    } 

我真的很感激任何幫助,或者如果你可以簡單告訴我我缺少的東西以及我需要進一步研究的內容。請注意,我是一名新的Swift開發人員,所以我的知識有限,如果我犯了明顯的錯誤,我很抱歉。

回答

1

這是因爲單元格可在集合視圖中重用。在你的代碼中,你正在創建新的視圖,所以在第一個位置的單元格重新加載後,你有更多的標籤。

改爲創建新視圖(UIImageView,UILabel),您應該在xib(storyboard)上創建它們並每次更新。

+0

我不記得具體是什麼,但是當我在故事板中創建帶有視圖的UICollectionView時,有一些我無法手動編寫它的功能。我被建議這樣做。沒有故事板的代碼沒有辦法做到這一點?對不起,我只是想確保在重寫我的應用程序的大部分之前 –

+0

我指出正在重新創建視圖後,我能夠解決它。看到我的答案。我只是在重新創建它們之前刪除它們。這可能不是很好的做法,但它會改寫應用程序。我接受你的答案,因爲它幫助我解決了這個問題。 :)謝謝你 –

+0

是的,刪除所有視圖將解決這個問題,但它會對性能產生很大的影響。在CollectionView(和TableView)中重複使用視圖,因爲從頭開始創建視圖非常重要。 – Mateusz

0

我只是想將此作爲評論添加到Mateusz中,因爲我知道這只是進一步閱讀的鏈接,但由於缺乏聲譽點,我不允許。

我對iOS開發也很新,並且使用了Apples「Getting Started」 - 指南,它很好地解釋了TableViews的工作原理。 CollectionsView基本上是相同的,所以我建議你閱讀本章,看看他們如何在故事板中創建單元格。

https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/CreateATableView.html#//apple_ref/doc/uid/TP40015214-CH8-SW1

//拉爾斯

+0

我意識到這一點,並開始使用這個應用程序時,正在使用精確的教程。然而,在某個地方(我認爲是當我想要定製單元格時,故事板限制了我,並且我被告知要通過代碼來完成它。現在,如果我不能這樣做,我的整個項目將不得不重寫。 –

0

好了,所以以後我周圍的一些玩解決它。我要感謝Mateusz您指出我的觀點正在重建,所以我加了這段代碼創建視圖之前:

let subViews = myCell.subviews 
      for subview in subViews{ 
       if (subview is UILabel) { 
        print("removing..") 
        subview.removeFromSuperview() 
       } 
if (subview is UIImageView) { 
        print("removing..") 
        subview.removeFromSuperview() 
       } 
      } 

這將刪除舊創建的視圖,並沒有粘貼過任何添加新的。

相關問題