So I came up with a couple of FriendFace challenges:
- Look up the gender of each person based on their first name
- Pull a random man's or woman's photo based on the results of Step 1
- Display that photo in the main List view along with their name and email address
(Anyone know how to scale an image in hackingwithswift.com's implementation of Markdown?)
Eagle-eyed readers will notice that the gender in some of these images doesn't match the gender of the name (see first record.) That's because I did a random gender/random image just to give everyone an idea of what I'm shooting for.
What I'd REALLY like to brainstorm with the forum here is the proper way to code the routines that will actually do the URLSessions that look up the gender and pull the random photos. Here are the data and image sources that I'm working with.
Gender: I'm passing a SQL query through an API to a data.world project. (See https://data.world/howarder/gender-by-name) The specific code here is not really important -- it's just an URLSession POST that returns JSON in the format [{ "gender": "M"}], [{"gender": "F"}]. The reason it returns an array is because some names can be male or female, in which case it will return multiple records sorted by their probability. In any case, we just pull the gender from the first element returned.
For the images, I found https://randomuser.me. It contains 100 random female images and 100 random male images. The URLs used to pull an image are:
https://randomuser.me/api/portraits/women/[0...99].jpg or https://randomuser.me/api/portraits/men[0...99].jpg
In other words, https://randomuser.me/api/portraits/women/0.jpg is the first female image, https://randomuser.me/api/portraits/women/99.jpg is the last female image. Likewise for the "men" images.
The added twist on pulling the random images is to NOT PULL THE SAME IMAGE TWICE.
So my thinking is that I should add a gender field to the FriendFace struct just after the name field, but make it a computed property that issues the URLSession to data.world, using httpMaximumConnectionsPerHost = 3 in a URLSessionConfiguration to not abuse data.world's free access tier.
But I think the code to pull a random image from randomuser.me should be in the ContentView because we'll need two @State arrays to make sure we don't choose the same person twice:
@State private var women = [Int](0..<100)
@State private var men = [Int](0..<100)
So we create the URL to pull the image with:
if(name.gender == "F"){
let woman = women.remove(at: Int.random(in: 0..<women.count))
personImageURL = "https://randomuser.me/api/portraits/women/\(woman).jpg"
} else {
let man = men.remove(at: Int.random(in: 0..<men.count))
personImageURL = "https://randomuser.me/api/portraits/men/\(man).jpg"
}
This pulls a random integer from our 0..<100 women or men array, but removes it from the array so we can't choose it again.
So I've essentially figured out the code to DO all of that -- what I haven't figured out is the best way to code all of that so the lookups happen in the correct background threads at the correct time and return the results in the most thread-safe, orderly manner.
Anyone care to jump in and give their ideas?