✔︎ 오늘의 정리
- pagenation
- responder
- URLSession Header
Pagenation
오늘 과제로 이전에 했던 책벌레 프로젝트를 리팩토링했다.
extension MoreViewController: UITableViewDelegate, UITableViewDataSource, UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
// queryText(검색어)가 비었다면 종료
guard !queryText.isEmpty else { return }
// 이 for문에서 pagenation이 구현된다.
// indexPath(각 셀의 위치)의 배열인 indexPaths를 돌면서 비교한다.
// 그 안에서 만약 indexPath가 bookList.count가 같다면 그 부분이 페이지의 끝이라는 소리니까
// 페이지가 끝나기 전에 데이터를 가져오는 조건을 설정해 준다.
// 또, 중요한 점이 json 데이터를 가져올 때 meta section에서 페이지가 끝났는지 볼 수 있는 is_end가 있다. (queryString 값은 각 json마다 다를 수 있음)
// 이 is_end를 서버에서 매번 가져오는데, 이 페이지가 끝 페이지가 아닐 때 새 페이지를 로드할 수 있으므로 이 값이 false일 때 로드하도록 한다.
// 또한, 최대 페이지 값을 설정해 주어 서버에서 제공해 주는 데이터의 페이지값을 넘는 걸 요청하여 오류가 나지 않도록 한다.
// Kakao 책 검색 API의 경우에는 size와 page 값은 최대 50까지였다.
for indexPath in indexPaths {
if bookList.count - 1 == indexPath.row && isEnd == false && page < 30 {
// 위 조건이 맞으면 새 페이지를 가져와야 하므로, 페이지 수를 증가시킨다.
page += 1
// 이후 callRequest(text:page:) 함수를 실행하여 서버에 데이터를 요청한다.
APIHelper.shared.callRequest(text: queryText, page: page) { book in
guard let book else { return }
self.bookList.append(contentsOf: book.documents)
self.isEnd = book.meta.isEnd
}
}
}
}
Responder
뷰 컨트롤러 안에 테이블뷰를 넣고서 키보드 내려가는 걸 구현을 안 해 놔서 키보드가 안 내려갔다 .. ㅋ.ㅋ
키보드가 내려가는 법을 구현하는 데에는 (내가알기로는) 두 가지가 있는데, responder를 이용하는 방법과 endediting을 이용하는 방법이 있다.
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true)
}
일케 ^_^
근데 보니까 resignFirstResponder() 반대는 뭐였지? 싶엇다...
이전에 키보드 이야기할 때 Responder 관련해서 배우고 hitTest 이야기가 나왔을 때 responderChain을 들었던 걸루 기억해서 대략적인 내용을 정리해 보려고 한다. 생각보다 내용이 많은 것 같아서 정리는 차차 하기로 하고!!
먼저! responder란 뭘까?!
responder는 이벤트를 핸들링하고 처리할 수 있는 객체들로, UIResponder의 인스턴스들을 말한다. UIKit은 이벤트가 발생하면 responder에게 전달하고, 해당 뷰는 자신이 그 이벤트를 처리하거나 다른 responder에게 넘긴다. 여기서 responderChain의 개념이 나오게 되는데, 이 responderChain은 responder가 해당 이벤트를 다른 responder에게 넘겼을 때, 누구에게로 이벤트가 이동하는지에 대해서 보여주고 있기 때문이다.
그래서 이런 그림이 나오게 되는데, UILabel, UITextField, UIButton 모두가 각각의 responder들로, 이벤트를 받았을 때 본인이 처리하거나 아니면 그 상위 뷰에게 전달하게 된다. 각각의 상위 뷰는 UIView이니 UIView에게로 해당 이벤트를 전달하고, 각각 처리하지 않고 이벤트를 올려보내게 되면 ViewController, Window, Application까지 올라가게 되는 것이다.
아무튼 우리는 특정 method를 통해서 responder를 첫 번째로 지정하거나 현재 지정되어 있는 responder로 넘길 수 있다. 각 이벤트의 종류에 따라서 특정 이벤트를 핸들링하기 위해서는 그에 상응하는 method를 오버라이드하여 구현해야 하는데, 이건 가볍게 넘기도록 하고 앞서 이야기가 나온 `becomeFirstResponder`와 `resignFirstResponder`에 대해서 알아보려고 한다.
먼저, becomeFirstResponder의 경우에는 해당 객체가 첫 번째 responder이면 true를 반환하고 아니라면 false를 반환하는 method로, 해당 뷰로 이동했을 때 키보드를 자동으로 올려줄 때 사용한다.
반면, resignFirstResponder는 해당 객체가 첫 번째 객체일 때 event를 해제하고 response를 반환한다. 서치 버튼을 눌렀을 때 키보드를 내리는 기능을 구현하거나 할 때 사용한당.....
아오 나 진짜 열심히 썼는데 이 부분 다 날렸다 ♡♡ ㅠㅠ
이잉 짱나
https://developer.apple.com/documentation/uikit/uiresponder
UIResponder | Apple Developer Documentation
An abstract interface for responding to and handling events.
developer.apple.com
https://developer.apple.com/documentation/uikit/uiresponder/1621113-becomefirstresponder
becomeFirstResponder() | Apple Developer Documentation
Asks UIKit to make this object the first responder in its window.
developer.apple.com
https://developer.apple.com/documentation/uikit/uiresponder/1621097-resignfirstresponder
resignFirstResponder() | Apple Developer Documentation
Notifies this object that it has been asked to relinquish its status as first responder in its window.
developer.apple.com
Using responders and the responder chain to handle events | Apple Developer Documentation
Learn how to handle events that propagate through your app.
developer.apple.com
iOS의 Responder와 Responder Chain 이해하기
UIKit과 관련된 애플 문서를 볼 때 빈번하게 등장하는 Reponder Chain에 관련한 내용을 정리합니다. 여러 애플 문서를 참고하였으며, 포스트의 맨 아래 References에서 확인할 수 있습니다.
seizze.github.io
https://woozzang.tistory.com/144
[iOS] 리스폰더 체인 (Responder Chain) 이란? (feat. UIResponder, First Responder, UIEvent)
안녕하세요🐶 이번 시간에는 리스폰더 체인 (Responder Chain) 에 대해서 공부해보겠습니다. 리스폰더 체인을 공부하면 앱 내에서 이벤트가 어떤 방식으로 전달되는지 알 수 있게 될 것입니다. 이
woozzang.tistory.com
URLSession Header
let header = ["Authorization": "KakaoAK APIKey"]
func callSessionRequest(text: String, page: Int, completionHandler: @escaping (Book?) -> ()) {
guard let text = text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { return }
guard let url = URL(string: "https://dapi.kakao.com/v3/search/book?target=title&query=\(text)&size=20&page=\(page)") else { return }
print(text, url)
var request = URLRequest(url: url)
// request.httpMethod = "GET" // 기본이 get이므로 안 써줘도 ㄱㅊ
// request.addValue("KakaoAK APIKey", forHTTPHeaderField: "Authorization") // 하나하나 header 추가해 줄 때!!
request.allHTTPHeaderFields = header // 이런 식으로 한번에 Dictionary에 넣을 수 있음
// let defaultSession = URLSession(configuration: .default)
print("hello")
URLSession.shared.dataTask(with: request) { data, response, error in
print("it worked!")
if let error = error {
print("error", error)
completionHandler(nil)
return
}
guard let response = response as? HTTPURLResponse, (200...500).contains(response.statusCode) else {
completionHandler(nil)
return
}
print("result?")
print(String(data: data ?? Data(), encoding: .utf8))
do {
let result = try JSONDecoder().decode(Book.self, from: data!)
DispatchQueue.main.async {
completionHandler(result)
}
} catch {
print(error)
completionHandler(nil)
}
}.resume()
}
로엔 도움받앗는데
꿀팁 얻엇다 . . .
import Foundation
let headers = [
"accept": "application/json",
"Authorization": "API Key"
let request = NSMutableURLRequest(url: NSURL(string: "https://api.themoviedb.org/3/movie/movie_id?language=en-US")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error as Any)
} else {
let httpResponse = response as? HTTPURLResponse
print(httpResponse)
}
})
dataTask.resume()
TMDB API 사이트에서 보니까 예시가 있드라
좀 ,, 허망~~ 했음
https://developer.themoviedb.org/reference/movie-details
Details
Get the top level details of a movie by ID.
developer.themoviedb.org
3일째 안 올리고 잇던 ... 묵힌 TIL을 보내주려고 한다......
한번 날려먹어서 ㅠ_ㅠ 제대로 그래도 쓰고 싶어서 좀 끼적였는데 역시 날린 만큼은 쓰지 못하고 그냥 내버려두게 되드라
이번 주에 DB 배운 거 정리하고 싶은데 막상 또 이어진 거에 쓰려니까 싫고~~
그래서 그냥 놓아주기로 했다
앞으로 하루 지나면 어디까지 썼든간에 대강 정리해서 올리려구 한다
자꾸 늘어지는 것도 싫고 왠지 짐처럼 남아있는 게 싫어!!
어차피 내가 공부한 거 정리하자고 올리는 TIL인데 TIL을 쓰기 위해서 정리하는 게 싫어졋다
TIL은 러프하게~~!!!! 나중에 글을 딥하게 쓰면 되니까 ^___^
무조건 적어놓고 써놓고 일단 하는 게 중요하다
암튼!! 빠.
'TIL' 카테고리의 다른 글
[SeSAC] September 17, 2023 (0) | 2023.09.20 |
---|---|
[SeSAC] September 7, 2023 (0) | 2023.09.07 |
[SeSAC] September 1, 2023 (0) | 2023.09.02 |
[SeSAC] August 29, 2023 (2) | 2023.08.30 |
[SeSAC] August 28, 2023 (0) | 2023.08.29 |