ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 내가 필요한 다이어리2
    Swift/다이어리 2024. 4. 14. 21:28

    가보자고~

     

    갤러리에서 이미지 추가를 위해 작성된 ImagePicker 파일

    // 'UIViewControllerRepresentable' 프로토콜을 준수하는 구조체로
    // SwiftUI 뷰에서 UIKit의 View Controller를 표시하기 위해 사용
    struct ImagePicker: UIViewControllerRepresentable {
            
        // 바인딩된 UIImage - 선택된 이미지 표시
        @Binding var selectedImage: UIImage?
        // SwiftUI에서 제공하는 환경 값으로, 모달로 표시된 뷰를 닫는데 사용
        @Environment(\.presentationMode) private var presentationMode
        
        // 선택된 이미지가 없는 경우 기본 이미지로 설정
        var defaultImage: UIImage? = UIImage(named: "이미지추가")
        // UIImagePickerController에서 사용할 이미지 소스의 타입을 지정(.photoLibrary, .camera 등)
        var sourceType: UIImagePickerController.SourceType
        
        // ImagePicker의 초기화 메서드
        init(selectedImage: Binding<UIImage?>, sourceType: UIImagePickerController.SourceType, defaultImage: UIImage? = nil) {
            _selectedImage = selectedImage
            self.sourceType = sourceType
            self.defaultImage = defaultImage
        }
        
        // UIViewControllerRepresentable 프로토콜에서 요구되는 메서드
        // UIImagePickerController를 생성하고 설정
        func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
            
            let imagePicker = UIImagePickerController()
            imagePicker.allowsEditing = true
            imagePicker.sourceType = sourceType
            imagePicker.delegate = context.coordinator
            
            return imagePicker
        }
        
        // UIViewControllerRepresentable 프로토콜에서 요구되는 메서드
        // 이미지 피커가 업데이트될 때 호출
        func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
            
        }
        
        // UIImagePickerController의 delegate를 처리하는 클래스
        // 이미지가 선택되면 해당 이미지를 selectedImage에 할당하고 이미지 피커를 닫음
        func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }
        
        final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
            
            var parent: ImagePicker
            
            init(_ parent: ImagePicker) {
                self.parent = parent
            }
            
            func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
                
                if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
                    parent.selectedImage = image
                }
                parent.presentationMode.wrappedValue.dismiss()
            }
        }
    }

     

    이미지를 추가하려면 따로 파일 파서 이런 메서드들을 작성해야 하는 듯

    기본 이미지도 넣으려고 조금 코드를 변경함

     

    // 캘린더 생성
    DatePicker(
        "Start Date",
        selection: $date,
        displayedComponents: [.date]
    )
    .datePickerStyle(.graphical)
    // 뷰가 나타날 때 dateFormat 설정
    .onAppear {
        dateFormat = dateFormatter.string(from: date)
    }
    // 날짜를 선택할 때 dateFormat 변경
    .onChange(of: date) { newValue in
        dateFormat = dateFormatter.string(from: newValue)
    }

     

    캘린더 부분도 조금 변경을 줌

    선택된 날짜를 다음 화면으로 넘겨줘야하기때문에 .onAppear과 .onChange를 사용했는데

    .onAppear은 뷰 나타날 때 한번 보여주고

    .onChange는 값이 변경될 때마다 보여주는 거

     

    // 내비게이션 설정
    .navigationBarTitle("일기 작성하기", displayMode: .inline)
    .navigationBarItems(trailing:
        Button("다음") {
        print("다음")
    })

     

    내비게이션 바도 설정해 줌

    중간에 이름은 "일기 작성하기" 로하고

    오른쪽에 "다음" 버튼도 만들어줌

     

    // TextEditor에 작성될 문자열
    @State var diary: String = ""
    
    let placeholder: String = "오늘의 일기를 작성해보세요!"
    
    var body: some View {
    	ZStack {
            TextEditor(text: $diary)
                .lineSpacing(10)
                .border(Color.gray, width: 3)
                
    		// TextEditor에 placeholder기능이 없어서 따로 조건문으로 생성
            if diary.isEmpty {
                Text(placeholder)
                    .foregroundColor(Color.primary.opacity(0.25))
            }
        }
    }

     

    이런 커스텀 같은 것도 해봤지요

    ZStack으로 겹치게 해서 아무것도 안 적혀있으면 placeholder기능이 있는 것처럼 구현

     

    // ImagePicker 표시
    .sheet(isPresented: $openPhoto) {
        ImagePicker(selectedImage: self.$image, sourceType: .photoLibrary)
    }

     

    마지막으로 .sheet을 사용해서 모달로 표시되는 이미지 선택기 구현

    $openPhoto 바인딩을 사용해서 모달이 열리거나 닫히는지 제어

    사용자가 '이미지 선택기 오픈 -> 이미지 선택 -> 해당 이미지 $image에 할당 -> 모달이 닫힘' 순으로 사용

     

    일단 틀만 만들어 보기~

    이미지 추가하는 거 넣었으니까 다음은 할만하겠지..?

    'Swift > 다이어리' 카테고리의 다른 글

    내가 필요한 다이어리5  (0) 2024.04.18
    내가 필요한 다이어리4  (1) 2024.04.16
    내가 필요한 다이어리3  (1) 2024.04.15
    내가 필요한 다이어리1  (0) 2024.04.13

    댓글

Designed by Tistory.