SwiftUI : Identifiable을 사용하여 연락처 뷰
연락처 뷰
이번에는 Identifiable
프로토콜을 사용하여 연락처 앱을 간단하게 만들어 보겠습니다.
메인 화면 구성
우선 contentView
에 사용자 연락처를 배열해주도록 하겠습니다. 우선 아래 이미지를 다운로드하여 Assets
에 넣어주겠습니다.
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
Model
에 Identifiable
을 지정해주고 변수를 만들어 주도록 하겠습니다.
//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 👇🏻