11

I'm updating a project to Swift 3 and came across the following warning which I can't seem to resolve.

fileprivate var filteredTitlesList: [String] = []

if let filteredTitle: String = filteredTitlesList[indexPath.row] as String { // 'Non-optional expression of type 'String' used in a check for optionals'

  // Do something

}

The answer to a similar question here didn't help me: Non-optional expression of type 'AnyObject' used in a check for optionals

Thanks a lot!

Community
  • 1
  • 1
nontomatic
  • 2,003
  • 2
  • 24
  • 38
  • Since `filteredTitlesList` is an array of `String` element, you needn't make a conversion of an element in this array to its own element type. Hencem, you really have no need for optional binding here. If `filteredTitlesList` was, say, an array of `Any` elements, you could perform an attempted conversion (`as?`) within an optional binding clause. – dfrib Nov 30 '16 at 09:09
  • You have array of `String`s and and get item from it, which is `String`, and then cast it to `String`. And expect it to be `nil`. Am I correct? – user28434'mstep Nov 30 '16 at 09:10
  • You have an array of strings, which - as per its declaration - can never be nil. So the entire `if` condition doesn't make sense. – Codo Nov 30 '16 at 09:10
  • Hello, thanks for the answers. Actually, I'm trying to check whether there exists a string in the array with the index of the selected indexPath.row and if so, assign it to filteredTitle. This was working perfectly in Swift 2.3. I still works, but now it gives a warning. – nontomatic Nov 30 '16 at 09:14
  • What is the `as String` check for? It makes the code compile (with warnings) but is otherwise useless. – If the index is valid then `filteredTitlesList[indexPath.row]` returns a string. If the index is not valid then `filteredTitlesList[indexPath.row]` crashes. – Martin R Nov 30 '16 at 09:23
  • Thanks again, for the help, turns out I didn't really need this check at all (posted below Jakob King's answer), sry for the trouble! – nontomatic Nov 30 '16 at 09:31

2 Answers2

13

You are trying to unwrap a value that is already unwrapped, and hence you are getting an error because it doesn't need unwrapping again. Change your if statement to look like the following and you should be golden:

if filteredTitleList.count > indexPath.row {
    let filteredTitle = filterdTitleList[indexPath.row]
}

Unfortunately there is no way to bind the variable within the if statement, hopefully they'll add one in the future.

Jacob King
  • 6,025
  • 4
  • 27
  • 45
  • This is generally a sane approach for bound check prior to accessing arrays by explicit indexing, but for the specific case of the OP, where an array is the data source for a tableview, there's and underlying problem in this datasource if `indexPath.row` is an invalid element index for `filteredTitleList` (so this would be a "fix" for a problem that is actually elsewhere). – dfrib Nov 30 '16 at 09:13
  • @dfri Agreed, in theory `filteredTitleList[indexPath.row]` should never exceed the range of the array, unless as you say, the data source is totally broken. I do encourage safe coding however so it's a good habit to make nonetheless. – Jacob King Nov 30 '16 at 09:15
  • I'm checking whether there exists a string at the given index path, and if so, assign it to filteredTitle. If not, nothing should be done. Excuse my ignorance but I don't see why this is not safe using the if let construction. – nontomatic Nov 30 '16 at 09:20
  • Ok, I get it now. Turns out, this code was a remains of when I did some testing and I never bothered to get rid of the if let statement since previous Xcode versions did not complain. The way it is set up in my code there will always be a string at that index, so I don't really need the check. I do see why your example code would make it safe. – nontomatic Nov 30 '16 at 09:30
1

Other possibility of this warning is when you're trying to put a statement eg:let keyboardFrame: CGRect = keyboardFrameValue.cgRectValue in conditional statement like if or guard

Ali
  • 2,427
  • 22
  • 25