묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결앨런 iOS 앱 개발 (15개의 앱을 만들면서 근본원리부터 배우는 UIKit) - MVVM까지
Drawing Cycle 관련 질문
안녕하세요, 강의 늘 잘 듣고 있습니다.다름이 아니라, 뷰의 레이아웃을 잡아주는 과정에서 Drawing Cycle & 생성자 중 어디에 무엇을 작성해야 할지 헷갈려서 개인적으로 알아보던 중 궁금증이 생겨서 질문드립니다! Drawing Cycle에 맞추어 뷰 업데이트하는 몇가지 예시init(생성자)subview 추가 (addSubview, stackView.addArrangedSubview)제약 생성 + NSLayoutConstraint.activate (1회)정적인 스타일(폰트, 색, axis, spacing 등)즉, ‘한번 바뀌고 안 바뀔 것들’을 세팅해 준다.updateConstraints()상태에 따라 레이아웃이 바뀔 때 (expanded/collapsed, 이미지 크기 토글, padding 변경, 어떤 뷰 숨김에 따른 높이 변경)constraint를 프로퍼티로 보관해두고updateConstraints()에서 constant 바꾸거나 isActive 토글필요 시 setNeedsUpdateConstraints() 호출즉, ‘동적으로 바뀔 레이아웃’을 세팅해 준다.layoutSubviews()frame이 계산된 뒤의 후처리를 수행해줘야 할 때 (그림자 경로, cornerRadius 등 frame의 정보가 필요한 것들) 먼저 제가 정리한 바는 다음과 같습니다.그런데, constraint를 updateConstraint() Drawing Cycle 내에서 지정해주는 강의 내 파트와 살짝 충돌이 발생하더라구요.GPT 및 개인적인 공부를 통해 확인했을 때에는,'constraint가 여러번 중복 적용될 수도 있으므로, 동적으로 constraint를 변경할 상황이 아니라면 생성자에서 초기화해주는 것이 좋다'라고 이해했습니다.동적으로 변경되지 않는 기본 레이아웃 제약은 생성자에서 설정하는 것이 원칙적으로 더 적절한지, 아니면 updateConstraints()에서 설정하는 방식도 올바른 패턴인지 궁금합니다.어떤 방식이 더 권장되는지 명확히 알고 싶습니다..!
-
해결됨앨런 iOS 앱 개발 (15개의 앱을 만들면서 근본원리부터 배우는 UIKit) - MVVM까지
앱 제작 시 주로 코드로 작성하시는 이유가 있을까요?
안녕하세요, 해당 강의 18:00분 경에 앨런님께서 말씀하신 '앱을 만들 때 주로 코드로 만든다'라는 말씀에 궁금증이 들어 질문 남깁니다.UIKit을 통해 앱을 제작하실 때, 스토리보드 대신 주로 이전 강의 섹션과 같이 주로 코드를 이용해 UI를 구성한다는 말씀이신가요?스토리보드와 코드 둘 다 짧게나마 겪어본 제 입장에서는, 세그웨이를 수행하는 것 제외 스토리보드가 더욱 많은 이점이 느껴져서요.대표적으로는 VC에 UI 관련한 코드가 없어 더욱 VC가 본인의 책임에 집중하게 된다는 생각도 들고, 코드로 UI를 짜다 보면 하나 둘 빼먹게 될 확률도 높아지는 것 같아서요(스토리보드에서는 이를 바로 에러로 잡아주지만, 코드는 잡아주지 않기도 하구요)어떤 부분에 의해, 주로 코드로 UI를 구성하는 것을 선호하는지가 궁금합니다!
-
해결됨앨런 iOS 앱 개발 (15개의 앱을 만들면서 근본원리부터 배우는 UIKit) - MVVM까지
델리게이트 패턴 관련 질문
영상 초반부(00:30 - 04:00)에 대한 의문점이 생겨 질문 남깁니다!텍스트필드의 경우 VC(뷰컨트롤러)와 '완전히 분리된 객체'이며 유저와 직접적인 커뮤니케이션을 하고, 버튼의 경우 VC와 '직접적인 커뮤니케이션을 한다' 라고 하셨는데, 이 부분에서 살짝 의문이 듭니다.텍스트필드와 버튼의 차이가 동작의 형태나 이벤트 흐름의 복잡성에서 발생한다는 점에는 공감하지만, 버튼 역시 UITextField와 마찬가지로 VC와는 별도의 객체로 존재하고, 이벤트 발생 시 target–action 메커니즘을 통해 결과를 VC로 전달하는 구조로 이해하고 있습니다.이런 관점에서 봤을 때, “버튼은 VC와 직접 커뮤니케이션한다”는 표현이 개념적으로 어떤 의미를 가지는지 조금 더 설명을 부탁드려도 될까요?
-
해결됨앨런 iOS 앱 개발 (15개의 앱을 만들면서 근본원리부터 배우는 UIKit) - MVVM까지
수강 기간 연장 부탁드릴 수 있을까요?
구매 후에 늦게나마 시작해서 기간이 얼마 안남았네요ㅠ혹시 기간 연장이 가능할까요?
-
해결됨앨런 iOS 앱 개발 (15개의 앱을 만들면서 근본원리부터 배우는 UIKit) - MVVM까지
활용 앱 57강 질문입니다.
영상 1분경에 보면드래그해서 폴더랑 파일 순서 변경하시는데 저는 현재 xcode 26.2 버전 사용하고있는데요.최신버전에서는 폴더, 파일순서 변경이 안되는건가요?
-
해결됨앨런 iOS 앱 개발 (15개의 앱을 만들면서 근본원리부터 배우는 UIKit) - MVVM까지
활용 앱 30강 에러 질문입니다
let backButton: UIButton = { let button = UIButton(type: .custom) button.setTitle("Back", for: .normal) button.setTitleColor(.white, for: .normal) button.backgroundColor = UIColor.blue button.titleLabel?.font = .boldSystemFont(ofSize: 20) button.addTarget(self, action: #selector(backButtonTapped), for: .touchUpInside) return button }()backButton 설정시에 addTarget 첫번째 인자로 self 로 전달하니까 'self' refers to the method 'FirstViewController.self', which may be unexpected라는 warning 문구가 xcode 내에 표시되어서 xcode 에서 추천하는 방향대로 아래 코드블록 처럼 FirstViewController.self 로 전달하니까 backButton 클릭시 Exception 이 발생하는데요. button.addTarget(FirstViewController.self, action: #selector(backButtonTapped), for: .touchUpInside) 이 부분 왜 Excpetion 이 발생하는건지 궁금합니다.self 로 전달하면 문제는 없는데 경고문구가 나오는게 신경쓰입니다.경고문구를 없애고 버튼 클릭에도 문제가 없으려면 어떻게 하는게 좋을까요?Exception 문구는 아래와 같습니다.*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NextVC.FirstViewController backButtonTapped]: unrecognized selector sent to class 0x100e4a3d8'*** First throw call stack:(0x19df92964 0x19ae81814 0x19e02d140 0x19df1235c 0x19df1a200 0x1a4c49f58 0x1a4501154 0x1a4501498 0x1a44fdf08 0x1a450001c 0x1a4c7a2d4 0x1a4c7b734 0x1a4c5e170 0x1a3892d38 0x1a38a1e28 0x1a3894c50 0x1a38a2ee4 0x1a38a2374 0x28cd15560 0x19dee34cc 0x19df130b0 0x19df12fd8 0x19deeac1c 0x19dee9a6c 0x23fb18498 0x1a38c2df8 0x1a386be54 0x1a3997820 0x100e365cc 0x100e3653c 0x100e36648 0x19aed6e28)libc++abi: terminating due to uncaught exception of type NSException
-
미해결앨런 iOS 앱 개발 (15개의 앱을 만들면서 근본원리부터 배우는 UIKit) - MVVM까지
기초앱 17강 Contraints 설정 질문입니다.
6:09 쯤에 UIView 에 대해서 Add New Contraints 하실때따라해보면 Top alignment 가 맞지않는게 좀 다르게 설정이 되는것 같습니다.Inspector 패널에서 확인해보면Top Alignment Constraint 가First Item : View.topSecond Item : Safe Area.top이런식으로 적용되고있는데요.이부분 설정을 어떻게해야 강의에 나오는것 처럼 수직정렬이 반듯하게 적용이 되는걸까요?
-
해결됨앨런 iOS 앱 개발 (15개의 앱을 만들면서 근본원리부터 배우는 UIKit) - MVVM까지
기초 앱 4강 Type Any -> UIButton
뒤에 설명이 나오는지는 아직 모르겠는데 수강자 분들 참고하시라고 적어놓습니다... 강의에서 @IBAction 함수 선언할 때 sender Type 을 Any 에서 UIButton 으로 변경하는데 그 이유가 이건 sender 의 타입이 UIButton 이라는 걸 명확하게 하는 거라고 보면 되고 Any 로 놔두면 나중에 sender 를 써야할 때는 타입캐스팅을 해야 사용이 가능합니다. [UIButton] 인 경우 sender.backgroundColor = ... [Any] 인 경우if let myButton = sender as? UIButton {sender.backgroundColor }
-
미해결
스위프트, UIKit 에서 테이블 뷰 내 텍스트뷰 높이 조절
지금 당근마켓의 내물건 팔기를 구현하고 있습니다. 전체적으로 UITableView로 만들고 각 셀마다 맞는 셀을 구현했습니다. 텍스트 뷰에 글을 작성하면 텍스트뷰의 높이가 글자 수에 맞춰 늘어나는데, 이때 키보드는 화면 하단에 고정되어 있는것으로 판단됩니다. 그래서 아래와 같이 구현해봤습니다. class FeedViewController: UIViewController { // MARK: - Variable private let tableSection: [String] = ["이미지", "제목", "내용"] var selectedImages: [UIImage] = [] // MARK: - UI Components private let feedTableView: UITableView = { let tableView = UITableView(frame: .zero, style: .insetGrouped) tableView.separatorStyle = .none tableView.showsVerticalScrollIndicator = false tableView.alwaysBounceVertical = false tableView.isScrollEnabled = true return tableView }() ... // MARK: - Layout private var feedTableViewBottomConstraint: NSLayoutConstraint! private var registerButtonTopConstraint: NSLayoutConstraint! private func configureConstraints() { view.addSubview(feedTableView) view.addSubview(registerFeedButton) feedTableView.translatesAutoresizingMaskIntoConstraints = false registerFeedButton.translatesAutoresizingMaskIntoConstraints = false // 제약 조건 저장 feedTableViewBottomConstraint = feedTableView.bottomAnchor.constraint(equalTo: registerFeedButton.topAnchor, constant: -10) registerButtonTopConstraint = registerFeedButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -10) NSLayoutConstraint.activate([ // 테이블뷰 제약조건 feedTableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), feedTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), feedTableView.topAnchor.constraint(equalTo: view.topAnchor), feedTableViewBottomConstraint, // 버튼 제약조건 registerFeedButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 15), registerFeedButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -15), registerFeedButton.heightAnchor.constraint(equalToConstant: 50), registerButtonTopConstraint ]) // 키보드 노티피케이션 설정 setupKeyboardNotifications() } private func setupKeyboardNotifications() { NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil) } @objc private func keyboardWillShow(_ notification: Notification) { if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect { // 키보드가 올라오면 테이블뷰의 bottom을 키보드의 top에 맞춤 feedTableViewBottomConstraint.constant = -keyboardFrame.height + 100 UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() } } } @objc private func keyboardWillHide(_ notification: Notification) { // 키보드가 내려가면 테이블뷰의 bottom을 버튼의 top으로 복원 feedTableViewBottomConstraint.constant = -10 UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() } } 그리고 ContentInputCell 이라고해서 텍스트뷰를 입력하는 곳에는 아래와 같이 작성했습니다. // MARK: - UI Component private let contentTextView: UITextView = { let textView = UITextView() textView.text = "오늘 하루는 어땠나요? 😀" textView.backgroundColor = .systemBackground textView.layer.cornerRadius = 5 textView.layer.masksToBounds = true // 글자 수에 따라 크기가 늘어가게 하기 위함 textView.isScrollEnabled = false textView.textAlignment = .left textView.textContainerInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) textView.textColor = .secondaryLabel textView.backgroundColor = .systemBackground textView.font = UIFont.systemFont(ofSize: 16, weight: .bold) return textView }() ... private func configureConstraints() { contentView.addSubview(contentTextView) contentTextView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ contentTextView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), contentTextView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), contentTextView.topAnchor.constraint(equalTo: contentView.topAnchor), contentTextView.bottomAnchor.constraint(equalTo: contentView.keyboardLayoutGuide.topAnchor, constant: 5), contentTextView.heightAnchor.constraint(greaterThanOrEqualToConstant: 350) ]) } // MARK: - Extension: UITextViewDelegate extension ContentInputCell: UITextViewDelegate { func textViewDidChange(_ textView: UITextView) { guard let tableView = tableView else { return } let contentSize = textView.sizeThatFits(CGSize(width: textView.bounds.width, height: .infinity)) if textView.bounds.height != contentSize.height { tableView.contentOffset.y += contentSize.height - textView.bounds.height UIView.setAnimationsEnabled(false) tableView.beginUpdates() tableView.endUpdates() UIView.setAnimationsEnabled(true) } } } extension ContentInputCell { var tableView: UITableView? { var view = superview while view != nil && !(view is UITableView) { view = view?.superview } return view as? UITableView } }
-
미해결
스위프트를 통해 사진을 여러장 선택 후, 선택된 이미지를 어떻게 홤면에 표시하나요?
안녕하세요당근마켓에서 보면 저렇게 동그라미 버튼을 누르면 여러 장의 사진을 선택할 수 있고, 선택이 완료되면선택된 사진을 버튼 옆으로 보여주는데요 이걸 구현할 때 가장 왼쪽에 있는 버튼 하나 구현하고, 그 옆에 선택된 이미지는 컬렉션 뷰를 통해 보여주면 되나요? 제가 구현하려고 하는 방법은 가장 왼쪽은 UIButton으로 구현하고 BSImagePicker를 통해 여러 장의 이미지를 선택하고 선택한 이미지를 별도의 배열에 저장한 다음에 그 옆으로 컬렉션뷰를 구현하여 배열 내의 사진을 한 장씩 보여주는 방식으로 하려고 합니다.