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

SwiftUI : Identifiable을 사용하여 연락처 뷰

서근
QUOTE THE DAY

-
Written by SeogunSEOGUN

반응형

연락처 뷰

이번에는 Identifiable 프로토콜을 사용하여 연락처 앱을 간단하게 만들어 보겠습니다.

메인 화면 구성

우선 contentView에 사용자 연락처를 배열해주도록 하겠습니다. 우선 아래 이미지를 다운로드하여 Assets에 넣어주겠습니다.

User.zip
0.04MB

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            HStack {
                Image("Leon")
                    .resizable()
                    .scaledToFit()
                    .frame(height: 60)
                    .clipShape(Circle())
                VStack(alignment: .leading) {
                    Text("Leon")
                        .fontWeight(.black)
                    Text("+82 10 1234 6523")
                }
            }
        }
    }
}

그리고 HStack을 커맨드 우클릭해서 Extract Subview를 클릭해주고 이름은 contactRow라고 정해주겠습니다.

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            ContactRow()
        }
    }
}

struct ContactRow: View {
    var body: some View {
        HStack {
            Image("Leon")
                .resizable()
                .scaledToFit()
                .frame(height: 60)
                .clipShape(Circle())
            VStack(alignment: .leading) {
                Text("Leon")
                    .fontWeight(.black)
                Text("+82 10 1234 6523")
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Contact Model 생성

[swift 탬플릿] 을 새로 만들고 이름은 Contact라고 정해주겠습니다. 이제 위에 ContactRow를 동적으로 만들어주기 위해서 Contact ModelIdentifiable을 지정해주고 변수를 만들어 주도록 하겠습니다.

//Contact View

import SwiftUI

struct Contact: Identifiable {
    var id = UUID()
    
    var imagename: String
    var name: String
    var phone:String
    var email: String
    var address: String

}

let contacts = [
    Contact(imagename: "JohnWood", name: "John Wood", phone: "+82 10 1234 6523", email: "john@gmail.com", address: "애플시 스위프트구 이룡동 서근아파트 105동"),
    Contact(imagename: "Leon", name: "Leon", phone: "+82 10 1224 3423", email: "Leon@gmail.com", address: "애플시 스위프트구 이룡동 서근아파트 102동"),
    Contact(imagename: "JacquelineWallace", name: "Jacqueline Wallace", phone: "+82 10 3322 2223", email: "wallace@gmail.com" , address: "애플시 스위프트구 이룡동 서근아파트 105동"),
    Contact(imagename: "RaymondLong", name: "Raymond Long", phone: "+82 10 2234 1423", email: "ray@gmail.com" , address: "애플시 스위프트구 이룡동 서근아파트 101동"),
    Contact(imagename: "PerryMurphy", name: "Perry Murphy", phone: "+82 10 1134 4223", email: "murphy@gmail.com" , address: "애플시 스위프트구 이룡동 서근아파트 102동"),
    Contact(imagename: "TerraLee", name: "Terra Lee", phone: "+82 10 1234 3423", email: "Terra@gmail.com" , address: "애플시 스위프트구 이룡동 서근아파트 103동")
]

이렇게 사용자의 정보를 가져왔으니 ContentView로 돌아가서 ContactRow부분을 수정해주도록 하겠습니다.

코드 수정

struct ContactRow: View {
    
    //Contact View를 가져옴
    var contact: Contact
    
    var body: some View {
        HStack {
            Image(contact.imagename)
                .resizable()
                .scaledToFit()
                .frame(height: 60)
                .clipShape(Circle())
            VStack(alignment: .leading) {
                Text(contact.name)
                    .fontWeight(.black)
                Text(contact.phone)
            }
        }
    }
}

ContactRow의 값을 동적으로 수정해줬습니다. 그런데 ContentView에서 오류가 생겼죠? 코드를 아래와 같이 수정해주겠습니다.

struct ContentView: View {
    var body: some View {
        VStack {
            ContactRow(contact: contacts[0])
        }
    }
}

contacts의 첫번째 사용자 정보를 가져오는데 까지는 성공했습니다. 이제 list를 사용하여 사용자의 모든 정보를 나열해주도록 하겠습니다.

struct ContentView: View {
    var body: some View {
        VStack {
            List(contacts) { contact in
                ContactRow(contact: contact)
                
            }
        }
    }
}

자 이렇게 메인 리스트 화면을 구성했습니다. 

Detail View

다음으로는 사용자의 연락처를 누르면 상세 페이지에서 상제정보를 볼 수 있는 뷰를 생성해볼까 합니다. 

 

새로운 [swift 탬플릿] 을 하나 만들고 이름은 DetailView라고 정해주겠습니다. 그리고 다음과 같이 코드를 작성해주세요.

import SwiftUI

struct DetailView: View {
    //Contact를 불러옴
    var contact: Contact
    var body: some View {
        VStack {
            Image(contact.imagename)
                .resizable()
                .scaledToFit()
                .frame(width: 150, height: 150)
                .clipShape(Circle())
            
            Text(contact.name)
                .font(.system(size: 30, weight: .black))
        }
    }
}

DetailView의 프리뷰를 보고 싶다면 아래와 같이 수정해줘야 합니다. 그러면 contacts의 첫 번째 item이 프리뷰에 나타나게 됩니다.

struct DetailView_Previews: PreviewProvider {
    static var previews: some View {
        DetailView(contact: contacts[0])
    }
}

이제 Form 안에 상대 정보를 기입 해주는 코드를 작성해주겠습니다.

import SwiftUI

struct DetailView: View {
    var contact: Contact
    var body: some View {
        VStack {
               ...
            
            Form {
                HStack {
                    Text("전화번호")
                    Spacer()
                    Text(contact.phone)
                        .font(.callout)
                        .foregroundColor(.gray)
                
                }
                HStack {
                    Text("이메일")
                    Spacer()
                    Text(contact.email)
                        .font(.callout)
                        .foregroundColor(.gray)
                }
                VStack(alignment: .leading) {
                    Text("주소")
                    
                    Text(contact.address)
                        .font(.callout)
                        .foregroundColor(.gray)
                }
            }
        }
    }
}

아래 버튼도 추가해줄께요.

import SwiftUI

struct DetailView: View {
    var contact: Contact
    var body: some View {
        VStack {
            ...
            
            Form {
                ...
          
                }
                Section {
                    //메세지 보내기
                    Button(action: {
                        print("메세지를 보냅니다.")
                    }) {
                        HStack {                        
                        Image(systemName: "message.circle.fill")
                            .foregroundColor(.yellow)
                            Text("메세지 보내기")
                                .foregroundColor(.primary)
                        }
                    }
                    // 전화
                    Button(action: {
                        print("전화를 겁니다.")
                    }) {
                        HStack {                        
                        Image(systemName: "phone.circle.fill")
                            .renderingMode(.original)
                            Text("전화")
                                .foregroundColor(.primary)
                            
                        }
                    }
                }
            }
        }
    }
}

전화번호 이메일 주소 부분을 symbols이미지를 사용하여 조금 더 꾸며주도록 하는 것이 좋겠습니다.

VStack {
    
    
    Form {
        HStack {
            Image(systemName: "phone.circle.fill")
                .renderingMode(.original)
            Text("전화번호")
            Spacer()
            Text(contact.phone)
                .font(.callout)
                .foregroundColor(.gray)
            
        }
        HStack {
            Image(systemName: "at.circle.fill")
                .renderingMode(.original)
            Text("이메일")
            Spacer()
            Text(contact.email)
                .font(.callout)
                .foregroundColor(.gray)
        }
        VStack(alignment: .leading) {
            HStack {
                Image(systemName: "location.circle.fill")
                    .renderingMode(.original)
                Text("주소")
            }
            
            Text(contact.address)
                .font(.callout)
                .foregroundColor(.gray)
        }
        Section {
            ...
        }
    }
}

DetailView 전체 코드

<hide/>

import SwiftUI

struct DetailView: View {
    //Contact를 불러옴
    var contact: Contact
    var body: some View {
        VStack {
            Image(contact.imagename)
                .resizable()
                .scaledToFit()
                .frame(width: 150, height: 150)
                .clipShape(Circle())
            
            Text(contact.name)
                .font(.system(size: 30, weight: .black))
            
            Form {
                HStack {
                    Image(systemName: "phone.circle.fill")
                        .renderingMode(.original)
                    Text("전화번호")
                    Spacer()
                    Text(contact.phone)
                        .font(.callout)
                        .foregroundColor(.gray)
                    
                }
                HStack {
                    Image(systemName: "at.circle.fill")
                        .renderingMode(.original)
                    Text("이메일")
                    Spacer()
                    Text(contact.email)
                        .font(.callout)
                        .foregroundColor(.gray)
                }
                VStack(alignment: .leading) {
                    HStack {
                        Image(systemName: "location.circle.fill")
                            .renderingMode(.original)
                        Text("주소")
                    }
                    
                    Text(contact.address)
                        .font(.callout)
                        .foregroundColor(.gray)
                }
                Section {
                    //메세지 보내기
                    Button(action: {
                        print("메세지를 보냅니다.")
                    }) {
                        HStack {                        Image(systemName: "message.circle.fill")
                            .foregroundColor(.yellow)
                            Text("메세지 보내기")
                                .foregroundColor(.primary)
                        }
                    }
                    // 전화
                    Button(action: {
                        print("전화를 겁니다.")
                    }) {
                        HStack {                        Image(systemName: "phone.circle.fill")
                            .renderingMode(.original)
                            Text("전화")
                                .foregroundColor(.primary)
                            
                        }
                    }
                }
            }
        }
    }
}
struct DetailView_Previews: PreviewProvider {
    static var previews: some View {
        DetailView(contact: contacts[0])
    }
}

NavigationLink 연결

contentView로 돌아가서 NavigationView로 덮고 List부분에 NavigationLink를 추가해서 그 아이템을 누르면 DetailView로 이동하게끔 만들어주겠습니다.

struct ContentView: View {
    var body: some View {
        NavigationView {
            List(contacts) { contact in
                ContactRow(contact: contact)
                
            }
            .navigationBarTitle("연락처")
        }
    }
}

이제 NavigationLink를 추가해줍니다.

struct ContentView: View {
    var body: some View {
        NavigationView {
            List(contacts) { contact in
               
               NavigationLink(
                    destination: DetailView(contact: contact)) {
                        ContactRow(contact: contact)
                    }
                }
            .navigationBarTitle("연락처")
        }
    }
}

전체 코드

<hide/>

// ContentView

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            List(contacts) { contact in
                NavigationLink(
                    destination: DetailView(contact: contact)) {
                        ContactRow(contact: contact)
                    }
                }
            .navigationBarTitle("연락처")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
                .preferredColorScheme(.dark)
        }
    }
}

struct ContactRow: View {
    
    //Contact View를 가져옴
    var contact: Contact
    
    var body: some View {
        HStack {
            Image(contact.imagename)
                .resizable()
                .scaledToFit()
                .frame(height: 60)
                .clipShape(Circle())
            VStack(alignment: .leading) {
                Text(contact.name)
                    .fontWeight(.black)
                Text(contact.phone)
            }
        }
    }
}

// Contact View


import SwiftUI

struct Contact: Identifiable {
    var id = UUID()
    
    var imagename: String
    var name: String
    var phone:String
    var email: String
    var address: String

}

let contacts = [
    Contact(imagename: "JohnWood", name: "John Wood", phone: "+82 10 1234 6523", email: "john@gmail.com", address: "애플시 스위프트구 이룡동 서근아파트 105동"),
    Contact(imagename: "Leon", name: "Leon", phone: "+82 10 1224 3423", email: "Leon@gmail.com", address: "애플시 스위프트구 이룡동 서근아파트 102동"),
    Contact(imagename: "JacquelineWallace", name: "Jacqueline Wallace", phone: "+82 10 3322 2223", email: "wallace@gmail.com" , address: "애플시 스위프트구 이룡동 서근아파트 105동"),
    Contact(imagename: "RaymondLong", name: "Raymond Long", phone: "+82 10 2234 1423", email: "ray@gmail.com" , address: "애플시 스위프트구 이룡동 서근아파트 101동"),
    Contact(imagename: "PerryMurphy", name: "Perry Murphy", phone: "+82 10 1134 4223", email: "murphy@gmail.com" , address: "애플시 스위프트구 이룡동 서근아파트 102동"),
    Contact(imagename: "TerraLee", name: "Terra Lee", phone: "+82 10 1234 3423", email: "Terra@gmail.com" , address: "애플시 스위프트구 이룡동 서근아파트 103동")
]

// Detail View

import SwiftUI

struct DetailView: View {
    //Contact를 불러옴
    var contact: Contact
    var body: some View {
        VStack {
            Image(contact.imagename)
                .resizable()
                .scaledToFit()
                .frame(width: 150, height: 150)
                .clipShape(Circle())
            
            Text(contact.name)
                .font(.system(size: 30, weight: .black))
            
            Form {
                HStack {
                    Image(systemName: "phone.circle.fill")
                        .renderingMode(.original)
                    Text("전화번호")
                    Spacer()
                    Text(contact.phone)
                        .font(.callout)
                        .foregroundColor(.gray)
                    
                }
                HStack {
                    Image(systemName: "at.circle.fill")
                        .renderingMode(.original)
                    Text("이메일")
                    Spacer()
                    Text(contact.email)
                        .font(.callout)
                        .foregroundColor(.gray)
                }
                VStack(alignment: .leading) {
                    HStack {
                        Image(systemName: "location.circle.fill")
                            .renderingMode(.original)
                        Text("주소")
                    }
                    
                    Text(contact.address)
                        .font(.callout)
                        .foregroundColor(.gray)
                }
                Section {
                    //메세지 보내기
                    Button(action: {
                        print("메세지를 보냅니다.")
                    }) {
                        HStack {                        Image(systemName: "message.circle.fill")
                            .foregroundColor(.yellow)
                            Text("메세지 보내기")
                                .foregroundColor(.primary)
                        }
                    }
                    // 전화
                    Button(action: {
                        print("전화를 겁니다.")
                    }) {
                        HStack {                        Image(systemName: "phone.circle.fill")
                            .renderingMode(.original)
                            Text("전화")
                                .foregroundColor(.primary)
                            
                        }
                    }
                }
            }
        }
    }
}
struct DetailView_Previews: PreviewProvider {
    static var previews: some View {
        DetailView(contact: contacts[0])
            .preferredColorScheme(.dark)
    }
}

 

 

읽어주셔서 감사합니다🤟

 

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

 

Seogun95/SwiftUI_ContactApp

SwiftUI_Contact. Contribute to Seogun95/SwiftUI_ContactApp development by creating an account on GitHub.

github.com

 

 


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


서근


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