[iOS/부스트 코스] iOS 앱 프로그래밍: Sign Up(3) - 기능 구현하기
안녕하세요. 개발하는 정주입니다.
오늘은 네이버 부스트 코스 프로젝트 B-Sign Up의 화면 구성하기를 포스팅하려고 합니다.
기능 구현은 로그인 화면, 회원 가입(기본 정보) 화면을 1편, 회원 가입(부가 정보) 화면을 2편으로 나눴습니다.
목차
공통
텍스트 필드를 편집 중일 때 화면 빈 공간을 터치하면 키보드가 내려가고 편집이 종료되는 기능은 모든 화면에 적용되어야 합니다.
해당 기능 구현 및 분석은 따로 포스팅을 진행하였으니 확인해주시면 감사하겠습니다!
로그인 화면
로그인 화면에서 구현할 기능은 "가입을 완료하면 Id TextField에 값 넣기"입니다. 해당 프로젝트는 싱글턴 디자인 패턴을 적용했기에 큰 어려움은 없습니다.
override func viewWillAppear(_ animated: Bool) {
if let id = UserInfomation.shared.id {
self.idTextField.text = id
}
}
UserInfomation의 공유 객체인 shared의 id가 nil이 아니면 idTextField에 id 문자열을 넣습니다. 더 정확히 처리하기 위해서는 ""일 경우도 예외 처리해줘야 하지만 ""는 입력을 안 한 것과 동일하기에 따로 예외 처리하지 않았습니다.
회원 가입(기본 정보)
간단한 것부터 살펴보겠습니다.
비밀번호 체크
password를 입력하고 Check Password에는 Password와 동일한 문자열이 들어가야 합니다. 단순한 문자열 비교이므로 간단합니다.
if password != self.checkPasswordTextField.text {
return false
}
다음 버튼 상태 변경
다음 버튼은 기본적으로 비활성화이며 프로필 이미지를 포함하여 모든 정보가 입력되면 활성화 됩니다.
따라서 다음 버튼의 isEnabled 값을 아래 상황에서 변경해줘야 합니다.
- 각각의 Text Field가 입력, 편집될 때
- 자기소개 TextView가 입력, 편집될 때
- 프로필 이미지가 삽입될 때
Text Field
Text Field가 편집된다는 것을 아는 방법은 IBAction - Edit Changed를 이용하거나 Delegate를 이용하면 되는데요. 저는 Text Field는 IBAction을 이용하였습니다.
TextView
자기소개 입력은 TextView를 이용합니다. TextView는 Delegate를 사용해보았습니다. 텍스트뷰가 수정될 때 호출되는 textViewDidChange()를 구현하면 됩니다. (https://developer.apple.com/documentation/uikit/uitextviewdelegate/)
func textViewDidChange(_ textView: UITextView) {
let text = textView.text ?? ""
UserInfomation.shared.introduction = text
changeNextButtonState()
}
프로필 이미지
프로필 이미지에 대한 처리는 아래에서 다루겠습니다.
프로필 이미지
이미지 선택은 UIImagePickerController을 이용했습니다. 이번 프로젝트에서는 edit 기능이 필수이므로 PHPickerViewController를 사용하지 않았습니다. UIImagePickerController와 PHPickerViewController 비교 포스팅은 아래를 확인해주세요.
UIImagePickerController의 공식 문서를 먼저 보겠습니다.
https://developer.apple.com/documentation/uikit/uiimagepickercontroller/
Apple Developer Documentation
developer.apple.com
공식 문서에서는 UIImagePickerController를 "A view controller that manages the system interfaces for taking pictures, recording movies, and choosing items from the user's media library."라고 소개하고 있습니다.
저희는 "choosing items from the user's media library"를 구현해야 하므로 해당 클래스를 선택했습니다. 만약 사진 촬영 기능이 있었다면 더욱더 해당 클래스를 사용해야겠지요.
self.imagePickerController.sourceType = .photoLibrary //앨범에서 가져옴
self.imagePickerController.allowsEditing = true //수정 가능 여부
self.imagePickerController.delegate = self
사진 선택 후 편집까지 해줄 것이기 때문에 allowsEditing을 true로 해주고 delegate를 self로 설정해줍니다.
sourceType는 공식 문서를 먼저 보겠습니다.
안타깝게도 camera를 제외한 case는 Deprecated 되었습니다. 하지만 이번에 굳이 Deprecated 된 case를 선택한 건 이유가 있습니다.
공식 문서에서는 photoLibrary case 대신 PHPickerViewController를 사용하라고 하는데요. 해당 클래스는 iOS 14.0+에서 지원합니다. 현재 iOS는 15 버전까지 나왔는데 바로 아래 단계인 14부터 지원하는 클래스를 사용하기에는 이르다는 평가입니다.
공식 홈페이지의 점유율을 보면 약 10%의 유저가 14 미만의 버전을 사용하고 있습니다. 10%는 무시하기에는 굉장히 큰 수치이므로 굳이 photoLibrary 케이스를 사용했습니다.
UIImagePickerController Delegate는 UIImagePickerControllerDelegate, UINavigationControllerDelegate를 채택해주어야 합니다. 저희는 이미지 선택이 끝나면 ImageView에 세팅을 하려고 하기 때문에 관련 메서드를 구현해야 합니다.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
var profileImage: UIImage? = nil
if let photo = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
profileImage = photo //수정 이미지
} else if let photo = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
profileImage = photo //원본 이미지
}
self.profileImageView.image = profileImage
UserInfomation.shared.profileImage = profileImage
picker.dismiss(animated: true, completion: nil)
changeNextButtonState()
}
이미지가 선택되었다면 InfoKey에서 적절한 이미지를 가져와야 합니다.
InfoKey 리스트도 공식 홈페이지(https://developer.apple.com/documentation/uikit/uiimagepickercontroller/infokey)에 나와 있습니다.
저희는 편집된 경우 편집 이미지를, 편집을 하지 않았다면 원본 이미지를 가져와야 합니다. 따라서 editedImage 키의 값을 먼저 확인 후 없다면 originalImage를 확인하고 가져옵니다.
이미지가 선택되었을 때 싱글턴 공유 객체에 값을 대입, ImageView에 이미지를 설정, UIImagePicker를 dismiss 하고 다음 버튼의 활성화 여부도 변경해줍니다.
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
Picker에서 완료가 아닌 취소 버튼을 누른 경우엔 UIImagePicker를 dismiss 해줍니다.
마무리 잡담
오늘은 로그인 화면과 회원 가입(기본 정보) 화면의 기능 구현에 대해 포스팅하였습니다.
다음 포스팅에서는 회원 가입(부가 정보) 화면의 기능 구현에 대해 설명하겠습니다.
감사합니다!
아직은 초보 개발자입니다.
더 효율적인 코드 훈수 환영합니다!
공감과 댓글 부탁드립니다.