iosfilterhigher-order-functionsxcode10swift4.1

Map function changes in Xcode 10


I have a variable declared as var noOfPlayers: [PlayerDetail]! Now let's say I have the property declared as var playerReadyStatus: Bool = true inside PlayerDetail. Now for each element inside noOfPlayers, I want to change this property of PlayerDetail. I'm using map to achieve this like

 func resetPlayerStatus(){
        noOfPlayers = noOfPlayers.map{ $0.playerReadyStatus = false; return $0} 
    }

This used to work fine in Xcode 9 but when I updated to Xcode 10 it says Value of type '[PlayerDetail]' has no member 'playerReadyStatus' Did something change in map function in Xcode 10? What should be the new approach for this using map?


Solution

  • Why this error is happening

    As of Swift 4.2, ImplicitlyUnwrappedOptional is removed from the type system and is replaced with an attribute. This means that the type of [PlayerDetail]! becomes [PlayerDetail]? (an optional array of PlayerDetail elements) with an attribute stating that it may be implicitly unwrapped when used.

    Since the type of noOfPlayers is [PlayerDetail]?, your code is using the Optional map(_:). It checks if the value is nil and applies the transform on the unwrapped value if it's non-nil. This means that if noOfPlayers is non-nil, the unwrapped [PlayerDetail] value is passed into the closure. The array of player details doesn't have a playerReadyStatus property, which is why you're seeing the Value of type '[PlayerDetail]' has no member 'playerReadyStatus' error.

    How to solve it.

    You probably don't need to have an optional array of players. It's possible that you could just change the type to [PlayerDetail] but you may need to give it an initial value (for example an empty array) depending on how it is initialized.

    If you need to make the distinction between no array and an empty array, then you should treat it like a optional when working with noPlayers (and possibly change ! to ? in the declaration), for example:

    noOfPlayers = noOfPlayers.map { unwrappedNoOfPlayers in
        unwrappedNoOfPlayers.map { playerElement in 
            playerElement.playerReadyStatus = false; return playerElement 
        } 
    }