Skip to content

Instantly share code, notes, and snippets.

@byJeevan
Last active September 14, 2024 17:33
Show Gist options
  • Save byJeevan/f67485bf380e86d4f87a723ac383827c to your computer and use it in GitHub Desktop.
Save byJeevan/f67485bf380e86d4f87a723ac383827c to your computer and use it in GitHub Desktop.
SwiftUI Components & Extension that saves iOSDev time.
### UIKit is **EVENT-Driven** framework - We could reference each view in the hierarchy, update its appearance when the view is loaded or as a reaction on an event.
### SwiftUI is **Declarative, State Driven** framework - We cannot reference any view in the hierarchy, neither can we directly mutate a view as a reaction to an event.
Instead, we mutate the state bound to the view. Delegates, target-actions, responder chain, KVO .. replaced with Closures & bindings.
@byJeevan
Copy link
Author

byJeevan commented Mar 1, 2021

Tabbar/ TabView creation - VStack as parent.

       VStack {
           
           TabView {
             
               
               Text("Video Tab")
                   .font(.system(size: 30, weight: .bold, design: .rounded))
                   .tabItem {
                       Image(systemName: "video.circle.fill")
                       Text("Live")
                   }
               
        
                
               Text("Profile Tab")
                   .font(.system(size: 30, weight: .bold, design: .rounded))
                   .tabItem {
                       Image(systemName: "person.crop.circle")
                       Text("Profile")
                   }
           }
           .accentColor(.red)
           .onAppear() {
               UITabBar.appearance().barTintColor = .white
           }
       }

Tint color and selection/highlight color of tab changed.

@byJeevan
Copy link
Author

byJeevan commented May 15, 2021

Click/Tap/Select/Touch event to view:

    @State private var isPresented = false

<your view>.gesture(DragGesture(minimumDistance: 0)
                                                        .onChanged { value in
                                                            if isPresented {
                                                                print("Touch down")
                                                            }
                                                            isPresented = false
                                                        }
                                                        .onEnded { value in
                                                            print("Touch up")
                                                            isPresented = true
                                                        }
                                                )
                                            

@byJeevan
Copy link
Author

byJeevan commented Nov 4, 2021

.navigationBarHidden(true) is not constructed for NavigationView instead, it should be it's child.

@byJeevan
Copy link
Author

byJeevan commented Nov 4, 2021

Return a view from a function - that checks some conditions.
PS: return types : some View vs AnyView vs View
Ref: https://stackoverflow.com/questions/62895948/how-to-return-a-view-type-from-a-function-in-swift-ui

@ViewBuilder func WidgetDetail(wOption: WidgetOptions) -> some View {
        switch wOption.id {
        case 0:
            CountryPicker()
        default:
            Text("Widget Not implemented")
        }
    }

@byJeevan
Copy link
Author

byJeevan commented Nov 5, 2021

Present view Modally (fullscreen) [ for iOS 14.0+]

         @State var isQuizPlayPresented = false
            
            Button(action: {
                  isQuizPlayPresented.toggle()
              }) {
                  Text("Get Started")
              }
              .padding()
              .fullScreenCover(isPresented: $isQuizPlayPresented, onDismiss: nil, content: QuizPlayView.init)

Dismiss a presented view (modally)

    @Environment(\.presentationMode) private var presentationMode // define
     self.presentationMode.wrappedValue.dismiss() // In button action

Advanced:

            .fullScreenCover(isPresented: $isResultView,
                             onDismiss: {
                self.presentationMode.wrappedValue.dismiss() // Dismisses current view along with Child view dismissed
            }, content: {
                QuizResultView(totalScore: 10) // Pass custom parameter to child view
            })

@byJeevan
Copy link
Author

Make the width of element fill till parent width

        VStack(alignment: .center) {
          Rectangle()
            .frame(height: 0.0) // -------- note this 
           Text("SHOW DETAILS")
        }
        .background(.yellow)
        

@byJeevan
Copy link
Author

byJeevan commented Apr 11, 2024

Basic Rail :

struct QuizRail: View {
  
  var body: some View {
    ScrollView(.horizontal) {
      HStack(spacing: 16) {
        ForEach((1...10), id: \.self) {_ in
          Rectangle()
            .frame(width: 150, height: 200)
            .cornerRadius(8)
        }
      }
      .padding(.horizontal, 16)
    }
  }
}

@byJeevan
Copy link
Author

List without separator (from iOS 15.0+)

          List {
            ForEach(items, id: \.self) { item in
              Text("item here")
                .listRowSeparator(.hidden)

            }
          }
          .listStyle(.plain)

@byJeevan
Copy link
Author

☢️ A workaround calculated the height of ScrollView

  @State var heightCalculated = 0.0

  var body: some View {

    ScrollView {
      ForEach(0..<10) { i in
        Text("\(i)")
      }
      .background(
        GeometryReader { proxy in
          Color.clear.onAppear { 
            heightCalculated = proxy.size.height
            debugPrint(proxy.size.height)
          }
        }
      )

    }
    .frame(height: heightCalculated)
  }

@byJeevan
Copy link
Author

To make Content view as parameter. A better way to build Generic views.

struct ContainerView<Content: View>: View {
  @ViewBuilder var content: Content
    
  var body: some View {
    content
  }
}


// Usage
ContainerView{
  ...
}

@byJeevan
Copy link
Author

Debugging:

  1. let _ = Self._printChanges() print statement to trace view lifecycle
  2. let _ = print("Update XYZView") We use this print to trace whether the body of Particular view (eg. SpyView) is executed or not.

ref: https://sarunw.com/posts/how-to-do-print-debugging-in-swiftui/

@byJeevan
Copy link
Author

To make fullscreen view to fill entire screen:

ZStack {
   Text("Hello").background(.yellow)
}
.frame(maxWidth: .infinity, maxHeight: .infinity) // this is important
.background(.blue)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment