[SeSAC] September 4, 2023

✔︎ 오늘의 정리

  • 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에게 넘겼을 때, 누구에게로 이벤트가 이동하는지에 대해서 보여주고 있기 때문이다.

 

https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/using_responders_and_the_responder_chain_to_handle_events

그래서 이런 그림이 나오게 되는데, 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

https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/using_responders_and_the_responder_chain_to_handle_events

 

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

https://seizze.github.io/2019/11/26/iOS%EC%9D%98-Responder%EC%99%80-Responder-Chain-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0.html

 

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