TransWikia.com

Break music player into usable components in SwiftUI

Code Review Asked on January 2, 2022

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()
    }
}

One Answer

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()
    }
}

Answered by pawello2222 on January 2, 2022

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP