궁금한 내용을 검색해보세요!
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
서근 개발노트
티스토리에 팔로잉
SWIFTUI/Others

SwiftUI : Redacted ( onAppear / disabled ) 콘텐츠 모자이크

서근
QUOTE THE DAY

-
Written by SeogunSEOGUN

반응형

Redacted 에 대해 알아보겠습니다.

Redacted(reason: .placeholder)

iOS 14에서 SwiftUI에는 모든 콘텐츠를 redact 하는 새로운 한정자(modifier)가 있습니다. 새로운 view 한정자가 있는 모든 view.redacted(reason:) 을 적용할 수 있습니다.

이 한정자에는 이유 한정자(reason modifier)가 필요한데, 이는 이 redact 작업의 이유를 SwiftUI에 알려줍니다.

 

현재 Apple은 한 가지 reason modifier 만 제공하고 있습니다. (reason: .placeholder)

Text("Hello, SwiftUI!")
    .redacted(reason: .placeholder)

이름에서 알 수 있듯이 .placeholder reason modifier는 실제 콘텐츠가 로드되기 전에 .placeholder로 사용되는 방식으로 콘텐츠를 redact(수정)합니다.

프로필 만들기

간단하게 프로필 하나를 만들어 보겠습니다.

struct ContentView: View {
    var body: some View {
        VStack{
            Image("mydog")
                .resizable()
                .frame(width: 140, height: 140)
                .clipShape(Circle())
            
            Text("서근")
                .font(.title)
                .fontWeight(.bold)
            
            Spacer().frame(height: 30)
            
            VStack(alignment: .leading, spacing: 12) {
                HStack {
                    Image(systemName: "envelope.circle.fill")
                        .renderingMode(.original)
                    Text("ksj083895@gmail.com")
                }
                HStack {
                    Image(systemName: "phone.circle.fill")
                        .renderingMode(.original)
                    Text("+82 10 1234 5678")
                }
                HStack {
                    Image(systemName: "network")
                        .foregroundColor(.yellow)
                    Text("seons-dev.tistory.com")
                }
                
            }
            
            Spacer().frame(height: 30)
            
            Button(action: {
                print("프로필을 업데이트 합니다.")
            }){
                Text("Update Profile")
                    .frame(width: 200, height: 40)
                    .background(Color.orange)
                    .cornerRadius(10)
                    .foregroundColor(.white)
            }
        }
    }
}

이렇게 프로필 코드를 만들고 여기에 .redacted(reason:) 한정자를 적용해 보겠습니다. 상단 VStack이 끝나는 지점에 이 한정자를 추가해줍니다.

struct ContentView: View {
    var body: some View {
        VStack {...}
       .redacted(reason: .placeholder)       
    }
}

reason modifier 는 모든 하위 View 에 전달됩니다.

.unredacted()

일부 Viewredact하지 않으려면 View.unredacted() 를 사용하여 적용된 reason modifier를 제거할 수 있습니다.

 

만약 서근의 상세정보에 아이콘만 보이게 해주고 싶다면 아래와 같이 수정합니다.

            VStack(alignment: .leading, spacing: 12) {
                HStack {
                    Image(systemName: "envelope.circle.fill")
                        .renderingMode(.original)
                        .unredacted()
                        
                    Text("ksj083895@gmail.com")
                }
                HStack {
                    Image(systemName: "phone.circle.fill")
                        .renderingMode(.original)
                        .unredacted()
                        
                    Text("+82 10 1234 5678")
                }
                HStack {
                    Image(systemName: "network")
                        .foregroundColor(.yellow)
                        .unredacted()
                        
                    Text("seons-dev.tistory.com")
                }
            }

startNetworkCall - 지연 효과

앱이 실행되고 나서 3초의 지연시간 뒤에 프로필의 상세 내역이 나타나게 하고 싶다면 아래와 같이 startNetworkCall() 이라는 함수를 만들어 줘야 합니다.

import SwiftUI

struct ContentView: View {  

    @State private var isLoading = false
    
    var body: some View {...}
    
    func startNetworkCall() {
        isLoading = true
        //3초 지연 후, 로딩이 완료됨
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            isLoading = false
            
        }
    }
}

이렇게 함수@State를 만들어줬으니 이제 호출을 해줄 차례입니다. VStack 바깥쪽에 .onAppear을 사용하여 그 안에 만들어준 함수를 넣어줍니다.

 

삼항연산자를 사용하여 isLoadingtrue이면 .placeholder을 실행 그게 아니면 empty

 

즉, .redacted(reason: isLoading ? .placeholder : []) 라는 구문도 수정해주겠습니다.

    VStack {...}    
    
        .onAppear { startNetworkCall() }
        //isLoading이 true이면 .placeholder을 실행 그게아니면 empty
        .redacted(reason: isLoading ? .placeholder : [])
    }
    
    func startNetworkCall() {
        isLoading = true
        //3초 지연 후, 로딩이 완료됨
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            isLoading = false
            
        }
    }
}

로딩이 되지 않았을 경우 버튼 비활성화

위 코드에서 한 가지 문제점이 있습니다. 아직 프로필이 로딩되지 않았음에도 불구하고 버튼을 클릭하면 버튼이 활성화가 됩니다.

 

로딩이 완료되기 전에는 버튼을 클릭해도 활성화되지 않게 하려면 Button.disabled(isLoading) 을 추가해줘야 합니다.

            Button(action: {
                print("프로필을 업데이트 합니다.")
                
            }){
                Text("Update Profile")
                    .frame(width: 200, height: 40)
                    .background(Color.orange)
                    .cornerRadius(10)
                    .foregroundColor(.white)
            }
            .disabled(isLoading)

이제 캔버스를 런 해보면 앱이 실행되고 난 후 3초 뒤에 프로필 상세 내역이 나타나고, 로딩이 되지 않았을 때는 버튼이 활성화되지 않는 것을 확인할 수 있습니다.

 

전체 코드

<hide/>

import SwiftUI

struct ContentView: View {
    
    @State private var isLoading = false
    
    var body: some View {
        VStack{
            Image("mydog")
                .resizable()
                .frame(width: 140, height: 140)
                .clipShape(Circle())
            
            Text("서근")
                .font(.title)
                .fontWeight(.bold)
            
            Spacer().frame(height: 30)
            
            VStack(alignment: .leading, spacing: 12) {
                HStack {
                    Image(systemName: "envelope.circle.fill")
                        .renderingMode(.original)
                        .unredacted()
                    Text("ksj083895@gmail.com")
                }
                HStack {
                    Image(systemName: "phone.circle.fill")
                        .renderingMode(.original)
                        .unredacted()
                    Text("+82 10 1234 5678")
                }
                HStack {
                    Image(systemName: "network")
                        .foregroundColor(.yellow)
                        .unredacted()
                    Text("seons-dev.tistory.com")
                }
                
            }
            
            Spacer().frame(height: 30)
            
            Button(action: {
                print("프로필을 업데이트 합니다.")
                
            }){
                Text("Update Profile")
                    .frame(width: 200, height: 40)
                    .background(Color.orange)
                    .cornerRadius(10)
                    .foregroundColor(.white)
            }
            .disabled(isLoading)
        }
        
        .onAppear { startNetworkCall() }
        //isLoading이 true이면 .placeholder을 실행 그게아니면 empty
        .redacted(reason: isLoading ? .placeholder : [])
    }
    
    func startNetworkCall() {
        isLoading = true
        //3초 지연 후, 로딩이 완료됨
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            isLoading = false
            
        }
    }
}

 

읽어주셔서 감사합니다🤟

 

본 게시글의 전체코드 GitHub 👇🏻

 

Seogun95/SwiftUI_Redacted_TUT

SwiftUI 에서 Redacted 사용법에 대해 알아봅시다. Contribute to Seogun95/SwiftUI_Redacted_TUT development by creating an account on GitHub.

github.com

 


잘못된 내용이 있으면 언제든 피드백 부탁드립니다.


서근


위처럼 이미지 와 함께 댓글을 작성할 수 있습니다.