|
| 1 | +# TIL |
| 2 | + |
| 3 | +## 배운 것 |
| 4 | +* tableView |
| 5 | + |
| 6 | + 데이터와 뷰는 따로 동작하기 때문에 데이터가 달라지면 그에 맞게 뷰를 갱신해야 함 |
| 7 | + |
| 8 | + 한번에 갱신해주기 위해서 사용 할 수 있는 메소드 - tableView.reloadData() |
| 9 | + |
| 10 | + reloadData()는 전체를 다 그리기 때문에 좋아요 기능 처럼 해당 셀만 변경이 있는 경우 reloadRows()를 사용할 수 있음 |
| 11 | + |
| 12 | + 커스텀셀은 cellForRowAt에서 cell의 index를 알려주어야 함. indexPath를 지정하는 dequeueReusableCell 함수를 사용함 |
| 13 | + |
| 14 | + ```swift |
| 15 | + let cell = tableView.dequeueReusableCell(withIdentifier: "SearchTableViewCell", for: indexPath) as! SearchTableViewCell |
| 16 | + ``` |
| 17 | + |
| 18 | + tableView의 함수 중 rowHeight를 지정하는 함수를 사용해도 되고, viewDidLoad에서 tableView.rowHeight = 250처럼 모든 행의 높이가 같을때 지정해줄 수 있음 |
| 19 | + |
| 20 | +* tableView에서 좋아요 기능 구현 |
| 21 | + |
| 22 | + 여러 방법이 존재하지만 간단하게 구현할 수 있는 방법은 tag |
| 23 | + |
| 24 | + tag를 사용할 수 있는 이유는 데이터인 배열 index와 셀의 index와 tag의 값을 동일하게 가지고 갈 수 있기 때문 |
| 25 | + |
| 26 | + step 1: cell의 button에 tag값을 indexPath.row로 설정 및 addTarget으로 액션을 설정 |
| 27 | + |
| 28 | + step 2: 좋아요를 누르면 데이터의 해당 row값의 bool 값을 변경한다.(true-false, toggle()함수로 표현 가능) |
| 29 | + |
| 30 | + step 3: 데이터가 변경되면 reloadRow함수를 호출 |
| 31 | + |
| 32 | + step 4: cellForRowAt에서 해당 행의 이미지가 변경되도록 isLiked변수에 따라 이미지 변경 처리 |
| 33 | + |
| 34 | + |
| 35 | +* 스크롤 시 셀이 재사용되면서 생길 수 있는 문제 |
| 36 | + |
| 37 | + 스크롤하면서 indexPath값에 따라 data가 변하게 되는데 cell이 재사용되면서 UI가 변경되지않는 경우가 발생함 |
| 38 | + |
| 39 | + 수정을 요청한 부분만 변경이 되기 때문에 cell의 UI는 변경을 해주지 않으면 이전에 사용되던 것을 그대로 사용함 |
| 40 | + |
| 41 | + 이를 방지하기 위해 100% 모든 경우를 cellForRowAt에서 처리함 (if - else) |
| 42 | + |
| 43 | +* Type Casting |
| 44 | + |
| 45 | + 인스턴스 타입을 확인하거나 자신의 인스턴스 타입을 다른 타입의 인스턴스인 것 처럼 사용할 때 활용 |
| 46 | + |
| 47 | + 타입 캐스팅은 타입에 힌트만 주는 것. 실제 인스턴스 타입은 메모리에 남아 있음 |
| 48 | + |
| 49 | + `is` 어떤 클래스의 인스턴스 타입인지, 어떤 데이터 타입인지 확인 가능 |
| 50 | + |
| 51 | + DownCasting |
| 52 | + |
| 53 | + 부모 클래스 타입을 자식 클래스 타입으로 다운해서 캐스팅 |
| 54 | + |
| 55 | + as? : 다운캐스팅에 성공할 경우 인스턴스, 실패할 경우 nil |
| 56 | + |
| 57 | + as! : 옵셔널 반환 불가. 성공할 경우 인스턴스, 실패할 경우 runtime error |
| 58 | + |
| 59 | + UpCasting |
| 60 | + |
| 61 | + 컴파일러가 캐스팅에 대한 성공을 확신할 수 있는 경우 as 사용 가능 |
| 62 | + |
| 63 | + 일반적으로 부모 클래스의 타입인 것을 알고 있을 때 as 사용 |
| 64 | + |
| 65 | + |
| 66 | +* Any & Anyobject |
| 67 | + |
| 68 | + Any: 모든 타입에 대한 인스턴스 담을 수 있음 |
| 69 | + |
| 70 | + Anyobject: 클래스의 인스턴스만 담을 수 있음 |
| 71 | + |
| 72 | + 컴파일 시점에선 타입을 알 수 없고 런타임 시점에 타입이 결정 |
| 73 | + |
| 74 | + |
| 75 | +## 생각해 볼 것 |
| 76 | + |
| 77 | +### awakeFromNib()의 역할과 어떤 코드를 작성하면 좋을지? |
| 78 | + |
| 79 | +nib파일(interface Builder에서 생성된 .xib파일)에서 로드된 객체가 초기화 된 후 호출되는 메소드 |
| 80 | + |
| 81 | +뷰와 아울렛의 액션 연결이 모두 완료된 상태이기 때문에 주로 뷰나 셀의 추가적인 초기 설정을 위해 사용 |
| 82 | + |
| 83 | +코드로 만든 뷰나 셀인 경우에 호출되지 않음. 코드로 뷰를 생성할 때는 init(frame: ) 함수 호출 |
| 84 | + |
| 85 | +셀이 재사용될 때 일정횟수 이상 호출되지 않기 때문에 변경되지 않는 고정적은 틀과 같은 UI설정할 때 사용 |
| 86 | + |
| 87 | +### xib / nib |
| 88 | + |
| 89 | +xib(xml interface builder) |
| 90 | + xml 기반. flat file(아무런 구조적 상관관계가 없는 레코드 파일)에 저장. |
| 91 | + 스토리보드도 xib형태를 띄고 있음 |
| 92 | + |
| 93 | +nib(next interface builder) |
| 94 | + 바이너리. 빌드시 xib파일이 nib로 컴파일되며 이를 관리하는 plist파일이 만들어짐 |
0 commit comments