DEV Community

shj
shj

Posted on

IOS Instagram App Login/Sign Up UI Cloning

I’ve recently learned the basics of SwiftUI, and instead of spending more time following tutorials, I want to start building something hands-on.
To practice the fundamentals, I’m going to recreate the Instagram Login and Sign-Up UI with reference to the images I randomly got from Google below:

Along the way, I’ll document the challenges I encounter and the solutions for them.

[Problem 1]
Unable to change the color of the Image by using .foregroundColor(.white)

[Solution]
One way is to include .renderingMode(.template) -> SwiftUI ignores the image’s original colors and uses the tint (foreground) color.

[Problem 2]
I am trying to make ---------OR--------- by utilizing Divider() but it keeps showing me something like this:


Setting the frame(height:1) and stretching it doesn't work too

[Solution]
Made two rectangles and set their height to 1 and stretched them while putting the text "OR" in the middle and it produced the result that I wanted.

Found out that in SwiftUI, when you use Divider() inside an HStack, it’s vertical by default (it stretches vertically), and setting frame(height: 1) only changes its height, not its width. That’s why it doesn’t show as a horizontal line.

[Problem 3]
Even after adding a NavigationLink and specifying its destination, it still doesn’t navigate to the desired view.
It's more like unclickable

[Solution]

The solution turned out to be simple — it was just a conceptual misunderstanding. In SwiftUI, a navigation container is required at the root level so the system knows where to push new screens. I simply needed to wrap everything inside a NavigationView.

[Problem 4]
Using NavigationView and NavigationLink produces navigation back button by default to revert back to the original view, but I want my two screens: Login and Sign Up pages to switch screens solely via "Log In" and "Sign Up" buttons which I just hid the default navigation back button using .navigationBarBackButtonHidden(true) but I noticed that repeatedly navigating back and forth between the two pages caused the app to become increasingly slow and unresponsive (wish I can put the recorded video to show the problem but unfortunately I can't paste video here .-.)

[Solution]
Okay so by right if the flow is with a single NavigationView:

  1. App launches → LoginView loads
    -> NavigationView is in LoginView (root).
    -> Stack is created (Stack 1).
    -> LoginView is at the bottom/root of the stack.
    Stack 1:
    ┌─────────────┐
    │ LoginView │ ← root
    └─────────────┘

  2. Press "Sign Up" button → NavigationLink to SignUpView
    -> SignUpView is pushed onto Stack 1 (top of the stack)
    Stack 1:
    ┌─────────────┐
    │ LoginView │
    └─────────────┘


    ┌─────────────┐
    │ SignUpView │ ← top
    └─────────────┘

  3. Press Back button in SignUpView
    -> Top view(SignUpView) is popped from Stack 1.
    -> I am back to LoginView (the root).
    Stack 1:
    ┌─────────────┐
    │ LoginView │ ← now top again
    └─────────────┘

However, what I coded was having NavigationView in both LoginView and SignUpView.
So technically what happens is:

  1. App launches → LoginView loads
    -> LoginView contains a NavigationView.
    -> SwiftUI creates a navigation stack (Stack 1).
    -> LoginView is the root/bottom of Stack 1.

  2. Tap "Sign Up" → NavigationLink to SignUpView
    -> Normally, NavigationLink pushes a view onto the current stack.
    -> But SignUpView also contains a NavigationView, so now:
    -> SwiftUI creates a new stack (Stack 2) inside the pushed SignUpView.
    -> Effectively, I’ve just pushed an entire stack (Stack 2) into the first stack (Stack 1)

  3. Inside SignUpView, tap "Log In"
    -> The new NavigationLink pushes a view onto Stack 2, not Stack 1 --> Stack 1 is still underneath, but it’s “dormant” until I pop back all the way.

So basically, if I keep repeatedly tap "Sign Up" and "Log In", it is going to create a nested stack which will cause extra memory/performance overhead explaining the slowness and unresponsiveness of the app

At first, I thought that if we wrapped the NavigationView inside ContentView and handled the screen transitions within the child views (LogIn and SignUp), we would maintain a single navigation stack that pushes new views onto it as they’re rendered. However, if we repeatedly tap “Sign Up” and “Log In,” the stack would keep growing indefinitely, even though it’s just one shared navigation stack.

Stack (top → bottom):
LoginView <-- new pushed
SignUpView
LoginView
SignUpView
LoginView <-- root

Hence this will still result in performance issue and cause memory pressure. So I was thinking the solution for this problem would be to pop back to the root or a specific view using programmatic navigation which means manipulate the stack programmatically

@State private var path = NavigationPath()
-> Creates a navigation container that manages the navigation history
-> path here is - initially empty
-> Which means we have a navigation stack, but it currently has no pushed destinations
-> NavigationPath = []
Stack exists, but nothing pushed yet

Login(path:$path) inside the braces
-> Whatever view we place inside the NavigationStack closure is considered its root view
-> SwiftUI automatically treats it as the base content shown when the path is empty
-> So when the stack is empty, it will render Login Page UI as default

.navigationDestination(for: String.self){screen in ....}
-> This tells SwiftUI: "When I append a String to path, show the corresponding view"
-> If the String pushed onto the stack is "SignUp" then render Sign Up page

So in my Login view, I bind the same path variable from parent view which is ContentView and when I tap on the Sign Up button, I want it to append "Sign Up" to path -> pushing "Sign Up" onto the stack which updates the state of path in parent view -> rendering Sign Up view ultimately. So the current stack will look like:
[Login View] -> Root
[Sign Up View] -> Top (get pushed)


In my Sign Up view on the other hand, when I tap on the Log In button, instead of appending to the path / pushing Log In view onto the stack again, I am removing everything on the stack -> This will result in empty stack which will render the view at the root level which is Login View that was intended

This way the stack won't grow continuously no matter how many times I tap onto Sign Up or Log In button and this solves the problem finally

The final end result:

Top comments (0)