-
Notifications
You must be signed in to change notification settings - Fork 3
iOS Trouble Shooting
woongs edited this page Nov 22, 2020
·
5 revisions
@woongs
, @kyungpyoda
의 문제 해결 과정 기록입니다.
- 문제
- 아래 그림과 같은 레이아웃을 원했으나 원하는 대로 나오지 않음
- 상황
- 두 view 사이의 관계를 맺으면 레이아웃이 제대로 잡히질 않음
-
estimated Size
: automatic or custom -
view1
:- view1.leadting == contentView
- view1.trailing >= view2.leading + constants
-
view2
:- view2.trailing == contentView
- view2.width == 120 or contentView.width * 0.3 or
-
- 두 view 사이의 관계를 맺으면 레이아웃이 제대로 잡히질 않음
-
추측원인
- collectionView의 estimated size가 automatic으로 되어있을 때 셀이 크기를 자동으로 계산하면서 레이아웃을 제대로 잡지 못하는 듯함.
-
해결
- collectionView Cell에서
override func systemLayoutSizeFitting
를 구현해서 직접 원하는 사이즈를 계산해준다. - 파라미터로 넘어오는
targetSize
는 delegate에서 설정해준 크기 대로 넘어온다. - estimatedSize 가 설정되어 있을 때 실제 사이즈를 어느 타이밍에 잡는지 좀 더 공부가 필요하다. delegate 에서 size를 조절해줘도 이후 제약에 따라 변하는 걸 보면 재조정이 들어갈텐데... 이것과 systemLayoutSizeFitting의 관계에 대해 공부가 필요하다.
- collectionView Cell에서
-
문제
- 위치를 contentView 왼쪽에 붙여뒀던 editing button이 클릭이 되지 않음.
-
상황
- Edit 버튼 클릭시 셀의 contentView를 이동시켜서 왼쪽에 붙여뒀던 editingButton을 보여주게 했는데, editingButton이 클릭되지 않는 문제
- CGAffineTransform 을 통한 translateX 조절
- 모습은 정상적으로 보이나 editView의 frame.x 가 그대로 -50
- contentView frame 조절
- 모습도 정상적으로 보이고 contentView의 frame.x도 원하는 대로 이동했으나 editingView의 frame은 그대로 -50 -> editingView는 contentView의 subView기 때문에 contentView와의 상대위치인 frame이 그대로 -50인건 당연 -> 근데 왜 터치는 안 되는가.....!!@#!@!#
- editingView frame 조절
- contentView는 그대로 있고 editingView만 이동함 (contentView.frame.x 와 editingView.frame.x가 모두 0)
-
추측 원인
-
editView의 frame이 변하지 않아서 선택이 되지 않는 것 같음contentView의 frame만 터치가 들어오는 것 같음
-
-
해결
- contentView가 아니라 계속 self로 셀 자체를 옮기고 있었음... ☠️
contentView의 bounds를 옮겨서 해결.
하지만 여전히 frame을 옮기면 editingView가 아니라 cell이 선택됨 실제로 터치되는 건 frame이 아니라 bounds의 영역인 것으로 보임 - UX적으로 버튼만이 아니라 셀이 클릭됐을 때 선택되는 게 좋을 것 같아서 그냥 frame을 뷰의 모습만 옮기는 방향으로 구현
- CollectionViewListCell을 보면 셀 영역 밖에 있다가 옮겨지는 게 아니라 origin은 cell의 origin과 같아 보임. editing mode일 때만 보여지게 하거나 붙이는 방법을 사용하는 듯. 그런식으로 해도 좋을듯 싶다.
- contentView가 아니라 계속 self로 셀 자체를 옮기고 있었음... ☠️
contentView의 bounds를 옮겨서 해결.
-
UIView의 extension으로
@IBIspectable
을 설정해뒀더니 storyboard가 너무 버벅거려서 제거하기로 결정.- 필요하다면 특정 View에서만 사용하고 아니면 코드로 구현!
-
제거했더니 아래와 같은 로그 발생
-
inspectable을 사용하면 아래와 같이 keyPath에 적용되서 사용하게 되는 구조인데, layer의 property에는 저렇게
layer.
을 붙여줘야 함.- 근데 기존의 코드에서는 get set을 사용해 그걸 변환해주고 있었어서, 그 부분이 빠져서 생기는 문제였음. 그림에서 처럼
layer.
을 붙여서 해결 - cornerRadius나 borderColor도 layer의 프로퍼티인데 이건
layer.
을 붙여주지 않아도 동작하는데 그 이유까지는 잘 모르겠음..
- 근데 기존의 코드에서는 get set을 사용해 그걸 변환해주고 있었어서, 그 부분이 빠져서 생기는 문제였음. 그림에서 처럼
- 문제
-
아래 예시처럼 클래스의 identifier을 타입 프로퍼티로 갖게 하고 이를 사용할 때가 있다.
// 콜렉션뷰의 Reusable Cell 생성 시 identifier를 지정해줄때 collectionView.dequeueReusableCell(withReuseIdentifier: AnyCell.identifier, for: indexPath) // 스토리보드 내의 뷰컨트롤러 객체를 identifier로 생성할때 self.storyboard?.instantiateViewController(identifier: AnyViewController.identifier) as! AnyViewController
-
나누어 작업하다보니 아래 처럼 두 가지 방법을 섞어 쓰게 되었다.
static var identifier: String { String(describing: self) } static let identifier: String = String(describing: AnyClass.self)
-
계산 작업이 덜 생기는, 저장 프로퍼티를 사용하는
static let identifier
로 통일하려고 했다.static let identifier: String = String(describing: self)
-
위 방법으로 시도했는데 아래와 같이 Crash 가 발생했다.
-
- 추측 원인
-
String(describing: self)
부분에서self
가 함수 그 자체로 들어가게 되어서identifier
가 제대로 지정되지 않아서 발생한 문제이다. - Computed Property의 대괄호 내에서 self 는 Class.Type 이 반환된다.
-
- 해결
static let identifier: String = String(describing: AnyClass.self)
-
describing
인자로AnyClass.self
와 같이 클래스 타입을 지정해서 넘겨주는 것으로 해결
-
- 문제
- segue가 달려있는 버튼에 selector도 같이 사용하고 싶은데 동작하지 않음 (filter가 edit 모드에서는 select All로 변함 -> filter는 segue, select All은 action을 하고싶음)
- 추측원인
- segue가 달려있으면 다음 화면으로 이동해야 하니 자연스럽게 IBAction과 같은 selector는 무시되는 것으로 보임(지극히 뇌피셜)
- 해결
-
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool
를 사용하면 segue 동작을 막을 수 있음 - 하지만 여전히 IBAction은 동작하지 않음.. 따라서 IBAction은 그냥 사용하지 않고 segue를 막는 부분에서 액션을 실행시켜줌.
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { guard currentState != .edit else { selectAllIssues() return false } return true }
-
-
문제
- select All이 클릭되면
관리하는 모델(또는 indexPath)를 선택되게 하고
cellForItemAt 에서 그 상태에 따라 cell.isSelected 값을 바꿔서 처리하려고 했으나,
이렇게 하고나면 그 다음에didSelectItemAt
나didDeselectItemAt
딜리게이트 메소드가 정상적으로 동작하지 않음
- select All이 클릭되면
-
상황:
- cellForItemAt 에서 cell.isSelected를 바꿔줌
if selectedIssues.contains(indexPath) { cell.isSelected = true } else { cell.isSelected = false }
- cell의 내부에서는 isSelected 변수에 따라 button의 모습을 바꿔줌
override var isSelected: Bool { didSet { editingButton.isSelected = isSelected } }
-
추측원인
- cell 자체의 isSelected 변수는 바뀌었으나, collectionView가 관리하는 selected cell에 셀이 정상적으로 등록되지 않는 것으로 보임.
-
해결
- cell.isSelected 뿐만 아니라 collectionView.selectItem까지 처리해줌
if selectedIssues.contains(indexPath) { cell.isSelected = true collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .init()) } else { cell.isSelected = false collectionView.deselectItem(at: indexPath, animated: false) }
- "(현재VC)To(이동할VC)"
"\(elf.self)To\(DestinationVC.self)"
- extension으로 분리
extension UIViewController {
func segueIdentifier(to destination: UIViewController.Type) -> String {
return "\(Self.self)To\(destination.self)"
}
}