3
\$\begingroup\$

I created a music player using swiftUI.I need to ask a question when I break up my player into usable components. How should I take this approach with the music player? because the music player is one view can't break up?

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image("albumCover")
            HStack{
                VStack {
                    Text("Album name")
                    Text("Artist name")
                }
                Spacer()
                Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/) {
                     Image(systemName: "heart")
                }
            }.padding()
            HStack{
                Text("0")
                Slider(value: /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Value@*/.constant(10)/*@END_MENU_TOKEN@*/)
                Text("-5:00")
            }.padding()
            
            HStack{
                Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/) {
                     Image(systemName: "shuffle")
                }
                Spacer()
                Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/) {
                     Image(systemName:"backward.end")
                }
                Spacer()
                Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/) {
                     Image(systemName: "play")
                }
                Spacer()
                Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/) {
                     Image(systemName: "forward.end")
                }
                Spacer()
                Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/) {
                     Image(systemName: "repeat")
                }
        
            }.padding()
            
                HStack{
                    Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/) {
                         Image(systemName: "hifispeaker")
                    }

                    Spacer()
                    Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/) {
                         Image(systemName: "music.note.list")
                    }
            
                }.padding()
            
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
\$\endgroup\$
2
\$\begingroup\$

I need to ask a question when I break up my player into usable components. How should I take this approach

The idea is to break a long and not so readable code into smaller parts. Also, each individual part needs to access variables etc.

For this you can use a private extension (unless it's in another file, then skip private):

struct ContentView: View {
    @State private var sliderValue = 1.0

    var body: some View {
        VStack {
            Image("albumCover")
            infoView
            sliderView
            actionsView
            bottomView
        }
    }
}
private extension ContentView {
    var infoView: some View {
        HStack {
            VStack {
                Text("Album name")
                Text("Artist name")
            }
            Spacer()
            Button(action: {}) {
                Image(systemName: "heart")
            }
        }
        .padding()
    }
}
private extension ContentView {
    var sliderView: some View {
        HStack {
            Text("0")
            Slider(value: $sliderValue)
            Text("-5:00")
        }
        .padding()
    }
}
private extension ContentView {
    var actionsView: some View {
        HStack {
            Button(action: {}) {
                Image(systemName: "shuffle")
            }
            Spacer()
            Button(action: {}) {
                Image(systemName: "backward.end")
            }
            Spacer()
            Button(action: {}) {
                Image(systemName: "play")
            }
            Spacer()
            Button(action: {}) {
                Image(systemName: "forward.end")
            }
            Spacer()
            Button(action: {}) {
                Image(systemName: "repeat")
            }
        }
        .padding()
    }
}
private extension ContentView {
    var bottomView: some View {
        HStack {
            Button(action: {}) {
                Image(systemName: "hifispeaker")
            }
            Spacer()
            Button(action: {}) {
                Image(systemName: "music.note.list")
            }
        }
        .padding()
    }
}

Note that you can declare sliderValue directly in ContentView:

struct ContentView: View {
    @State private var sliderValue = 1.0

and access it in the extension:

private extension ContentView {
    var sliderView: some View {
        Slider(value: $sliderValue)

But the code above still doesn't address the problem of repeating blocks of code in your ContentView. See how often this block is reused:

Button(action: {}) {
    Image(systemName: "hifispeaker")
}

What if you want to apply a modifier to every Image?

A solution may be to extract the repeating code to one function:

private extension ContentView {
    func customButton(imageName: String, action: @escaping () -> Void) -> some View {
        Button(action: action) {
            Image(systemName: imageName)
        }
    }
}

and use it like this:

private extension ContentView {
    var bottomView: some View {
        HStack {
            customButton(imageName: "hifispeaker", action: {})
            customButton(imageName: "music.note.list", action: {})
        }
        .padding()
    }
}
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.