Swift – if string is nil. don’t add it to the array

Swift – if string is nil. don’t add it to the array

I have an Array of Image links –

Array

Image

let alamofireSource = [AlamofireSource(urlString: Img1!)!, AlamofireSource(urlString: Img2!)!,
AlamofireSource(urlString: Img3!)!, AlamofireSource(urlString: Img4!)!]
slideshow.setImageInputs(alamofireSource)

some posts have only one image or two or three, and so on. so, sometimes image 2 (for example) is nil, In that case, I don’t want it to be added to the array, is that possible?

3 Answers
3

You can try ( Swift 4 )

let arr = [img1,img2].compactMap{$0}.map{AlamofireSource(urlString:$0)!}

or

let arr = alamofireSource.compactMap{$0}

for Swift 3

let arr = alamofireSource.flatMap{$0}

Thanks a trillion! It fixed the problem 🙂
– Sophie Bernard
Jul 3 at 10:22

This is Swift 4. You may want to add flatMap for Swift 3 or prior
– smnk
Jul 3 at 12:08

@SophieBernard Note that the approach in this answer (forcibly unwrapping the result of the initializer) may lead to a run-time exception, as the AlamofireSource(urlString:) initializer is a failable initializer. I’ve added an answer below showing one approach to safely unwrap the result of the possibly failing initialization, taking also into account the fact that the url strings themselves (Img1, … Img4 in your example) are optionals, and should also be safely unwrapped.
– dfri
Jul 7 at 23:10

AlamofireSource(urlString:)

Img1

Img4

so, sometimes image 2 (for example) is nil, In that case, I don’t want
it to be added to the array, is that possible?

Yes it is. Although I would go with Sh_Khan’s suggestion to use the compactMap method to achieve it, but it would be useless for your current case:

compactMap

Based on your code snippet, I’d assume that alamofireSource of type [AlamofireSource], but not [AlamofireSource?] and that’s because you are forcibly unwrap its elements (by adding ! to each of its elements). So far alamofireSource doesn’t contain nils (actually it could be more danger than just a declaration, your app might crash!)

alamofireSource

[AlamofireSource]

[AlamofireSource?]

!

alamofireSource

So first of all, I would recommend to remove the ! from alamofireSource:

!

alamofireSource

let alamofireSource = [AlamofireSource(urlString: Img1!),
AlamofireSource(urlString: Img2!),
AlamofireSource(urlString: Img3!),
AlamofireSource(urlString: Img4!)]

which means let it be as [AlamofireSource?], therefore you would gain the benefit of using compactMap(_:):

[AlamofireSource?]

compactMap(_:)

Returns an array containing the non-nil results of calling the given
transformation with each element of this sequence.

As:

let alamofireSourceWihoutNils = alamofireSource.compactMap { $0 }

Assuming you put your Optional url strings into an array, say urlStrings (of type [String?]), you can construct alamofireSource according to (Swift 4):

Optional

urlStrings

[String?]

alamofireSource

let alamofireSource = urlStrings.compactMap { $0.map(AlamofireSource.init) }

Which make use of the map(_:) operator of Optional and compactMap(_:) to unwrap the two-level optionality.

map(_:)

Optional

compactMap(_:)

Details

Your example contains two levels of optionality:

ImgX

String?

img1

img4

CapitalFirstLetter

init?(urlString: String, placeholder: UIImage? = nil)

AlamofireSource

First of all, lets gather the optional image links (imgX) into an array

imgX

let urlStrings = [url1, url2, url3, url4] // [String?]

You can combine the map(_:) operator of Optional with compactMap(_:) to safely unwrap and make use of the .some entires of urlStrings, thereafter collect the successful invocations of the failable initializer of AlamofireSource:

map(_:)

Optional

compactMap(_:)

.some

urlStrings

AlamofireSource

let alamofireSource = urlStrings.compactMap { $0.map(AlamofireSource.init) }

// or, use a named closure argument
let alamofireSource = urlStrings.compactMap { str in str.map(AlamofireSource.init) }

If using Swift 3, replace the compactMap(_:) invocation above with flatMap(_:):

compactMap(_:)

flatMap(_:)

let alamofireSource = urlStrings.flatMap { $0.map(AlamofireSource.init) }

// or, use a named closure argument
let alamofireSource = urlStrings.flatMap { str in str.map(AlamofireSource.init) }

By clicking “Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

發表留言