UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Question regarding ForEach usage for arrays.

Forums > Swift

Hi All,

Hope you're all well and have enjoyed the holiday period.

I hope you'll be able to help me with a question I have regarding ForEach usage, or manly how to stop/control execution. Basically the long and short of what I attempting to do is to get the first element out of a decoded JSON array and just use the first line of that first result to generate a "preview" for want of a better word, I have tried many methods all be them unsuccessfully to achieve this including putting the array into a new array and ForEaching through that, the code below is the closet I have come but this still shows one line of all the items array... close but not the idea.

ForEach(people.messages_from) { personIn in // Loops across an array of people, curently to and creates a navlink passing through their name
    NavigationLink(destination: PerDetail3(personNamed: personIn.name)) {
        HStack {
            Image(systemName: "message.circle")
                .frame(width: 44)
                .font(.title)
                .padding(.leading, 10)
                .foregroundColor(.purple)

            VStack(alignment: .leading) {
                Text("\(personIn.name)") // Displays the persons name
                    .font(.headline)
                ForEach(message.messages) { msg in // Loops through all messages in the messages array
                    //if(personIn.name == message.messages[0].bindingID) {
                    if(personIn.name == msg.bindingID) { // Links the persons name with a binding ID to make sure the message is theirs
                        //msg.content.enumerateLines { (line, _ in // Failed attempt at using enumerateLines...
                        //Text(message.messages[0].content) // Works brilliantly but for just one person and not all of them.
                        Text(msg.content) // Current code, works fine but displays all of the messages one line at a time, I only need the first one and one line here, think iMessage
                            .lineLimit(1)
                            .font(.subheadline)
                            .foregroundColor(Color("second"))
                    }
                }
            }
        }
    }
}

I have left my commented code in as when I use a direct reference like message.messages[0] without the ForEach loop it works but the issue then is it only works for the one person in the array not the two or three that exist, again I understand that the ForEach loop is doing exactly as it should, looping through all entries but my question is how can I stop its execution after returning the first result for the one person to then do the same again for the next and so on.

To give context, message is my JSON class, messages is an array of messages and bindindID is a key:value in the messages array.

Thanks for any help, its probably a simple solution and if you would like to "point" me in the right direction to a solution I would be very grateful.

3      

From what I see in your code, you have a battle between declarative programming and procedural programming.

I've programmed in Java, Python, and perhaps 1/2 dozen other obscure languages. Dictating each step of a solution is locked into my problem solving DNA. This gave me headaches when switching to declarative languages like SwiftUI.

First take a step back. Write down a few notes about what you want your view to show.

Do you want it to show a bunch of messages for just one person? Do you want it to show messages for a topic? Messages for a selected date range?

Establish some of your rules first.

Next look at your data. If you get thousands of messages from your JSON datastore and load them into your application, how do you store them. Let's assume you have them in a large array.

Then your question becomes, which of these messages do I want to pass to the view?

Don't pass all your messages to the view and demand the view make business decisions. Think of your view as a simple machine to generate screens, lists, and buttons. You have to provide it a box of items to display. But, and this is the important part, you should never ask avoid asking your view to make business decisions.

You seem to violate this principle in these lines of code:

ForEach(message.messages) { msg in // Loops through all messages in the messages array
                  // snip ------
       if(personIn.name == msg.bindingID) { //  This SMELLS like a business rule!

Data Model

I would argue that that you should have a data model file that holds all the messages. This code file also offers a few methods to filter your large data set into smaller, manageable data sets.

For example, your view might ask the user to click a name. And your user selects "Nigel". Your view passes this request to your data model asking "Do you have any messages for Nigel?"

Your data model yells back "Nigel's messages are coming right up! They'll be out in a second." The model, in turn, runs a few functions, and prepares a new box containing just Nigel's messages.

Once you have the smaller collection, the one containing just the messages you want to see in your view, then you pass this smaller array over to your view object!

Your view opens the box and sees a fresh set of messages. It knows exactly what to do with these. It pulls each one out, identifies the bits and pieces, and shoves each into custom made Text(), Slider(), Label(), or other view elements to be rendered on the screen. Your view doesn't care what you provided. It just grabs everthing, adds some lip gloss, and displays it all.

Don't ask your views to do any heavy lifting!

3      

For Each

I wrote some thoughts about ForEach in a different post. I describe ForEach as a view factory.

See here for more! ForEach Factory

3      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.