skip to Main Content

When I select a cell, I want to deselect it from the other cell. After making the selection, I cannot remove the selection from the previous cell. What is the reason of this ? Sorry. I know little English.

Enum

enum Page {
    case newest
    case populer
    case iPhone
    case iPad
    case mac
    case watch
}

ViewModel

class MainViewModel: ObservableObject {
    @Published var selectedTab = Page.newest
}

Category Model

struct Category: Identifiable {
    var id = UUID()
    var title: String
    var icon: String
    var color: Color
    var page: Page
}

Basic Category

let basicCategory = [
    Category(title: "En Yeniler", icon: "flame", color: .red, page: .newest),
    Category(title: "Popüler", icon: "star", color: .yellow, page: .populer),
]

Cell

struct TabView: View {
    var title: String = ""
    var icon: String = ""
    var color: Color
     var page: Page
    @ObservedObject var macMainVM = MainViewModel()
    var body: some View {
        
        Button(action: {
            withAnimation(.spring(response: 0.5, dampingFraction: 0.6, blendDuration: 0)) {
                
                self.macMainVM.selectedTab = self.page
            }
        }) {
            VStack {
                Image(systemName: icon)
                    .imageScale(.large)
                    .foregroundColor(color)
                Text(title)
                    .font(.custom("Oswald-Light", size: 14))
                    .fixedSize()
            }
            .padding(5)
//I emphasize the choice here
            .background(self.macMainVM.selectedTab == self.page ? RoundedRectangle(cornerRadius: 10).stroke(color) : nil)
            
        }
        .buttonStyle(PlainButtonStyle())
    }
}

ForEach

VStack {
   ForEach(basicCategory, id: .id) { item in
     TabView(title: item.title, icon: item.icon, color: item.color, page: item.page)
                }
            }

enter image description here

3

Answers


  1. Updated my answer with the working answer.

    The problem was that you were using @ObservedObject instead of a @StateObject

    Always use @StateObject for the parent view and @ObservedObject for the children view.

    import SwiftUI

    struct stackT: View {
       @StateObject var macMainVM = MainViewModel()
        var body: some View {
            VStack {
               ForEach(basicCategory, id: .id) { item in
                TabView(macMainVM: macMainVM, title: item.title, icon: item.icon, color: item.color, page: item.page)
                            }
                        }
        }
    }
    
    struct stackT_Previews: PreviewProvider {
        static var previews: some View {
            stackT()
        }
    }
    
    
    struct TabView: View {
        @ObservedObject var macMainVM: MainViewModel
        var title: String = ""
        var icon: String = ""
        var color: Color
        let page: Page
        var body: some View {
            
            Button(action: {
                withAnimation(.spring(response: 0.5, dampingFraction: 0.6, blendDuration: 0)) {
                    DispatchQueue.main.async {
                        self.macMainVM.globalTab = page
                        print(macMainVM.globalTab)
                    }
                }
            }) {
                VStack {
                    Image(systemName: icon)
                        .imageScale(.large)
                        .foregroundColor(color)
                    Text(title)
                        .font(.custom("Oswald-Light", size: 14))
                        .fixedSize()
                }
                .padding(5)
    //I emphasize the choice here
                .background(self.macMainVM.globalTab == self.page ? RoundedRectangle(cornerRadius: 10).stroke(color) : RoundedRectangle(cornerRadius: 10).stroke(.clear))
                
            }
            .buttonStyle(PlainButtonStyle())
        }
    }
    
    class MainViewModel: ObservableObject {
        @Published var globalTab = Page.newest
    
    }
    
    
    enum Page {
        case newest
        case populer
        case iPhone
        case iPad
        case mac
        case watch
        case none
    }
    
    struct Category: Identifiable {
        var id = UUID()
        var title: String
        var icon: String
        var color: Color
        var page: Page
    }
    
    let basicCategory = [
        Category(title: "En Yeniler", icon: "flame", color: .red, page: .newest),
        Category(title: "Popüler", icon: "star", color: .yellow, page: .populer),
        Category(title: "Another", icon: "book", color: .blue, page: .mac)
    ]
    
    Login or Signup to reply.
  2. Below are the approaches for single selection and multiple selection.

    1. For single selection you can pass Page as Bindings to subView.

    2. For multiple selection you can maintain a boolean state array, that can tell if current cell was already selected or not.

    Single Selection

    import SwiftUI
    
    enum Page:String {
        case newest
        case populer
        case iPhone
        case iPad
        case mac
        case watch
    }
    
    struct Category: Identifiable {
        var id = UUID()
        var title: String
        var icon: String
        var color: Color
        var page: Page
    }
    
    class MainViewModel: ObservableObject {
        @Published var selectedTab = Page.newest
    }
    
    struct TabView: View {
        var title: String = ""
        var icon: String = ""
        var color: Color = .red
        var page: Page
        @Binding var macMainVM :Page
        
        
        var body: some View {
            
            Button(action: {
                withAnimation(.spring(response: 0.5, dampingFraction: 0.6, blendDuration: 0)) {
                    
                    self.macMainVM = self.page
                }
            }) {
                VStack {
                    
                    Text("Tap")
                        .font(.custom("Oswald-Light", size: 14))
                        .fixedSize()
                }
                .padding(5)
                //I emphasize the choice here
                .background(self.macMainVM == self.page ? RoundedRectangle(cornerRadius: 10).stroke(color) : nil)
                
            }
            .buttonStyle(PlainButtonStyle())
        }
    }
    
    struct mainView:View{
        
        let basicCategory = [
            Category(title: "En Yeniler", icon: "flame", color: .red, page: .newest),
            Category(title: "Popüler", icon: "star", color: .yellow, page: .populer),
        ]
        
        @ObservedObject var macMainVM = MainViewModel()
        
        var body: some View {
            VStack {
                ForEach(basicCategory.indices) { index in
                    TabView(page: basicCategory[index].page,macMainVM: $macMainVM.selectedTab)
                }
            }
        }
    }
    

    Multiple Selection

       import SwiftUI
    
    enum Page:String {
        case newest
        case populer
        case iPhone
        case iPad
        case mac
        case watch
    }
    
    
    class MainViewModel: ObservableObject {
        @Published var selectedTab = Page.newest
        var stateArray:[Bool] = []
    }
    
    struct Category: Identifiable {
        var id = UUID()
        var title: String
        var icon: String
        var color: Color
        var page: Page
    }
    
    struct TabView: View {
    
        var title: String = ""
        var icon: String = ""
        var color: Color = Color.red
    
        var page: Page
        var count = 0
        var onIndex:Int
    
        @ObservedObject var macMainVM = MainViewModel()
    
        init(totalPage:Int,page:Page,onIndex:Int) {
            self.count = totalPage
            self.page = page
            self.onIndex = onIndex
            macMainVM.stateArray = [Bool](repeating: false, count: totalPage)
        }
    
        var body: some View {
    
            Button(action: {
                withAnimation(.spring(response: 0.5, dampingFraction: 0.6, blendDuration: 0)) {
    
                    if macMainVM.stateArray[onIndex] == false{
                        macMainVM.stateArray[onIndex] = true
                    }else{
                        macMainVM.stateArray[onIndex] = false
                    }
    
                    macMainVM.selectedTab = self.page
    
                }
            }) {
                VStack {
    
                    Text("Tap")
                        .font(.custom("Oswald-Light", size: 14))
                        .fixedSize()
                }
                .padding(5)
                //I emphasize the choice here
                .background(macMainVM.stateArray[onIndex] ? RoundedRectangle(cornerRadius: 10).stroke(color) : nil)
    
            }
            .buttonStyle(PlainButtonStyle())
        }
    }
    
    struct mainView:View{
        let basicCategory = [
            Category(title: "En Yeniler", icon: "flame", color: .red, page: .newest),
            Category(title: "Popüler", icon: "star", color: .yellow, page: .populer),
        ]
        //var model = MainViewModel()
        var body: some View {
            VStack {
                ForEach(basicCategory.indices) { index in
                    TabView(totalPage: basicCategory.count, page: basicCategory[index].page, onIndex: index)
                }
            }
        }
    }
    

    NOTE-: I haven’t explained what I did in deep, because it will be more understandable by looking into code.

    Login or Signup to reply.
  3. The most Easy way: You should just use shared object, which you are creating new one every time! I did not edit your code! I just used a shared model! that was all I done! Or you can use environmentObject, and that would also solve the issue without shared one! both way is working!

    enter image description here

    import SwiftUI
            
     struct ContentView: View {
                
    
        var body: some View {
        
                VStack {
                    ForEach(basicCategory, id: .id) { item in
                        TabView(title: item.title, icon: item.icon, color: item.color, page: item.page)
                    }
                }
                .background(Color.gray)
                
            }
        }
        
        
        enum Page {
            case newest
            case populer
            case iPhone
            case iPad
            case mac
            case watch
        }
        
        class MainViewModel: ObservableObject {
            
            static let shared: MainViewModel = MainViewModel() // <<: Here
            
            @Published var selectedTab = Page.newest
            
        }
        
        
        struct Category: Identifiable {
            
            var id = UUID()
            var title: String
            var icon: String
            var color: Color
            var page: Page
            
        }
        
        
        
        let basicCategory = [
            Category(title: "En Yeniler", icon: "flame", color: .red, page: .newest),
            Category(title: "Popüler", icon: "star", color: .yellow, page: .populer),
            Category(title: "iPhone", icon: "iphone.homebutton", color: .yellow, page: .iPhone),
            Category(title: "ipad", icon: "ipad.homebutton", color: .yellow, page: .iPad),
        ]
        
        
        struct TabView: View {
            
            let title: String
            let icon: String
            let color: Color
            let page: Page
            
            @ObservedObject var macMainVM = MainViewModel.shared // <<: Here
            
            
            var body: some View {
                
                
                
                Button(action: {
                    
                    withAnimation(.spring(response: 0.5, dampingFraction: 0.6, blendDuration: 0)) {
                        
                        macMainVM.selectedTab = page
                        
                    }
                }) {
                    
                    VStack {
                        Image(systemName: icon)
                            .imageScale(.large)
                            .foregroundColor(color)
                        Text(title)
                            .font(.custom("Oswald-Light", size: 14))
                            .fixedSize()
                    }
                    .padding(5)
                    .background(macMainVM.selectedTab == page ? RoundedRectangle(cornerRadius: 10).stroke(color) : nil)
                    
                }
                .buttonStyle(PlainButtonStyle())
                
                
                
            }
        }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search