6 Replies
      Latest reply on Mar 27, 2020 6:07 PM by OOPer
      ZoneX Level 1 Level 1 (0 points)

        I'm trying to display different information from an api but all the values are nil. How do I unwrap them?

         

        func update(with item: CurrentPlayer) {

                firstName?.text = item.firstName

                lastName?.text = item.lastName

                team?.text = item.team

                position?.text = item.positionCategory

                playImg?.image = UIImage(named: "Grey")

              

                imageController.fetchItemArtwork(url: item.photoUrl) {

                    (image) in

                    if let image = image {

                        DispatchQueue.main.async {

                            self.playImg?.image = image

                        }

                    }

                }

            }

        • Re: Trying to display on a collectionview cell.
          OOPer Level 8 Level 8 (5,675 points)

          How do your know  all the values are nil ?

           

          How do I unwrap them?

           

          You cannot unwrap nils, unless you want to crash your app.

           

          What is `imageController`? What is `fetchItemArtwork(url:)`? What is `CurrentPlayer`?

          I guess any of them are malfunctioning and you may need to fix them so that you can get non-nil values.

            • Re: Trying to display on a collectionview cell.
              ZoneX Level 1 Level 1 (0 points)

              I know they are nil because I tried to debug them and saw the values were nil so that was why they are not displaying. How can I display them then?

               

              ImageController is constant that takes the function fetchItemArtwork which takes a url and turns it into a UIImage. CurrentPlayer is my class with the values for update. This is my ViewController

               

              class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

               

                

                  @IBOutlet weak var collections: UICollectionView!

                

                

                  @IBOutlet weak var theSearch: UISearchBar!

                

                

                  var cPlayerArr = [CurrentPlayer]()

                

               

                

               

                  override func viewDidLoad() {

                      super.viewDidLoad()

                      let layout = UICollectionViewLayout()

                      downloadJSON {

                          self.collections.reloadData()

                          //print("***\(self.cPlayerArr)***")

                      }

                      self.collections.register(CurrentPlayerCell.self, forCellWithReuseIdentifier: "playercell")

                      self.collections.delegate = self

                      self.collections.dataSource = self

                

                  }

                

                  func downloadJSON(completed: @escaping () -> ()) {

                      let url = URL(string: "https://api.sportsdata.io/v3/nba/scores/json/Players?key=apiKey")

                    

                      URLSession.shared.dataTask(with: url!) {

                          (data, response, error) in

                          if error == nil {

                              do {

                                  //put data in here

                                  self.cPlayerArr = try JSONDecoder().decode([CurrentPlayer].self, from: data!)

                                  DispatchQueue.main.async {

                                      completed()

                                  }

                              } catch {

                                  print("JSON Error")

                              }

                          }

                          } .resume()

                  }

                       

                

               

                  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

                    

                      print(cPlayerArr.count)

                      return cPlayerArr.count

               

                  

                  }

                  

                    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

                    

                      let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "playercell", for: indexPath) as! CurrentPlayerCell

                    

                      let item = cPlayerArr[indexPath.row]

                   

                      cell.update(with: item)

                    

                      return cell

                  

                  }

                • Re: Trying to display on a collectionview cell.
                  OOPer Level 8 Level 8 (5,675 points)

                  saw the values were nil

                  Where did you see that? It is important because Xcode has some bug that it shows fake nil in some occasions.

                  Inspector of the debug area? Have typed some debugging command? Or some other way?

                   

                  ImageController is constant that takes the function fetchItemArtwork which takes a url and turns it into a UIImage.

                  Please show the code.

                   

                  CurrentPlayer is my class with the values for update.

                  Please show the code.

                   

                  This is my ViewController

                  I cannot find anything obviously wrong in your ViewController. Please show other parts of your code.

                    • Re: Trying to display on a collectionview cell.
                      ZoneX Level 1 Level 1 (0 points)

                      my text labels for example all have UILabel? nil. Part of my func update in the first question.

                       

                       

                       

                      Code 1: ImageController

                       

                      class FetchImage {
                      
                      
                      func fetchItemArtwork(url: URL, completion: @escaping (UIImage?) -> Void) {
                          let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
                              if let data = data,
                                  let image = UIImage(data: data) {
                                  completion(image)
                              } else {
                                  completion(nil)
                              }
                          }
                      
                          task.resume()
                      }
                      }

                       

                      Code 2: CurrentPlayer class

                      import Foundation
                      
                      struct CurrentPlayer: Codable, Hashable {
                          let photoUrl: URL
                          let firstName: String
                          let lastName: String
                          let positionCategory: String
                          let team: String
                         
                          enum CodingKeys: String, CodingKey {
                              case photoUrl = "PhotoUrl"
                              case firstName = "FirstName"
                              case lastName = "LastName"
                              case positionCategory = "PositionCategory"
                              case team = "Team"
                          }
                         
                          init(from decoder: Decoder) throws {
                          let values = try decoder.container(keyedBy: CodingKeys.self)
                          photoUrl = try values.decode(URL.self, forKey: CodingKeys.photoUrl)
                          firstName = try values.decode(String.self, forKey: CodingKeys.firstName)
                          lastName = try values.decode(String.self, forKey: CodingKeys.lastName)
                          positionCategory =  try values.decode(String.self, forKey: CodingKeys.positionCategory)
                          team = try values.decode(String.self, forKey: CodingKeys.team)
                      
                          }
                      }
                        • Re: Trying to display on a collectionview cell.
                          Claude31 Level 8 Level 8 (8,455 points)

                          Using the same identifier (such as firstNamle) for multiple purposes is really confusing.

                           

                          Where is firstName, as UILabel, defined ?

                           

                          It seems that firstName (as UILabel, not the String) is nil.

                          • Re: Trying to display on a collectionview cell.
                            OOPer Level 8 Level 8 (5,675 points)

                            Thanks for showing your code. I thought `image` given to the closure was nil reading all the values are nil. It seems I was wrong.

                            (Please notice that you have not clarified what all the values are in your first post.)

                             

                            Now you say all have UILabel? nil, you should better check some other things first.

                             

                            I need to guess and assume one more things,

                            - The method `update(with:)` is defined in your custom cell class `CurrentPlayerCell`

                             

                            So, how do you declare the text labels, how do you initialized them?

                             

                            - If they are declared as IBOutlets, check the storyboard if all the IBOutlets are properly connected in the prototype cell

                            - If not, check your code if you properly instantiate UILabels and add them as a subview of the cell