210617 Thu

Sunny·2021년 7월 4일
0

Today I Learned

목록 보기
80/88

학습 내용

  • 컬렉션뷰 UI 다시 바로 잡기 ^.ㅠ (스택뷰 적용?!)
  • 컬렉션뷰에도 데이타 불러오는거 마저 코드 적용하기 (커밋 해두기)
  • 처음 목록을 로드할 때, 사용자에게 빈 화면만 보여주는 대신, 로드 중임 보여주기 ⭐️

→ indicator 객체 띄워주면 된다고 함 !!! by 키오센세

1. 첫 번째 학습 내용: self.tableView.reloadData()

Instance Method
reloadData()

Reloads the rows and sections of the table view.

Discussion

Call this method to reload all the data that is used to construct the table, including cells, section headers and footers, index arrays, and so on. For efficiency, the table view redisplays only those rows that are visible. It adjusts offsets if the table shrinks as a result of the reload.

The table view’s delegate or data source calls this method when it wants the table view to completely reload its data.

It should not be called in the methods that insert or delete rows, especially within an animation block implemented with calls to beginUpdates() and endUpdates().

2. 두 번째 학습 내용: dataTask

Instance Method
dataTask(with:completionHandler:)

Creates a task that retrieves the contents of a URL based on the specified URL request object, and calls a handler upon completion.

func dataTask(with request: URLRequest, 
completionHandler: @escaping (Data?, URLResponse?, Error?)

Parameters

requestA URL request object that provides the URL, cache policy, request type, body data or body stream, and so on.

completionHandlerThe completion handler to call when the load request is complete. This handler is executed on the delegate queue.

If you pass nil, only the session delegate methods are called when the task completes, making this method equivalent to the [dataTask(with:)](https://developer.apple.com/documentation/foundation/urlsession/1410592-datatask) method.

This completion handler takes the following parameters:

  1. data

The data returned by the server.

  1. response

An object that provides response metadata, such as HTTP headers and status code. If you are making an HTTP or HTTPS request, the returned object is actually an [HTTPURLResponse](https://developer.apple.com/documentation/foundation/httpurlresponse) object.

  1. error

An error object that indicates why the request failed, or nilif the request was successful.

Return Value

The new session data task.

Discussion

By creating a task based on a request object, you can tune various aspects of the task’s behavior, including the cache policy and timeout interval.

By using the completion handler, the task bypasses calls to delegate methods for response and data delivery, and instead provides any resulting [NSData](https://developer.apple.com/documentation/foundation/nsdata)[URLResponse](https://developer.apple.com/documentation/foundation/urlresponse), and [NSError](https://developer.apple.com/documentation/foundation/nserror)objects inside the completion handler. Delegate methods for handling authentication challenges, however, are still called.

You should pass a nil completion handler only when creating tasks in sessions whose delegates include a [urlSession(_:dataTask:didReceive:)](https://developer.apple.com/documentation/foundation/urlsessiondatadelegate/1411528-urlsession) method.

After you create the task, you must start it by calling its [resume()](https://developer.apple.com/documentation/foundation/urlsessiontask/1411121-resume) method.

If the request completes successfully, the data parameter of the completion handler block contains the resource data, and the error parameter is nil. If the request fails, the data parameter is nil and the error parameter contain information about the failure. If a response from the server is received, regardless of whether the request completes successfully or fails, the response parameter contains that information.

3. 세 번째 학습 내용: Activity Indicator

Class
UIActivityIndicatorView

A view that shows that a task is in progress.

@MainActor class UIActivityIndicatorView : UIView

Overview

You control when an activity indicator animates by calling the [startAnimating()](https://developer.apple.com/documentation/uikit/uiactivityindicatorview/1622835-startanimating) and [stopAnimating()](https://developer.apple.com/documentation/uikit/uiactivityindicatorview/1622842-stopanimating) methods. To automatically hide the activity indicator when animation stops, set the [hidesWhenStopped](https://developer.apple.com/documentation/uikit/uiactivityindicatorview/1622837-hideswhenstopped) property to true.

You can set the color of the activity indicator by using the [color](https://developer.apple.com/documentation/uikit/uiactivityindicatorview/1622836-color)property.

인터넷에 activity Indicator 다들 엄청 쉽다는 듯이 얘기하는데

나는 안돼서 혼자 몇시간 끙끙 대다가 😥

덕복 & 제임스한테 물어보고 2분 만에 해결됐다 ^.ㅠ

진작에 물어보고 다른거 할걸... !! 🤦‍

고민한 점: Activity Indicator가 화면에 안보임

문제 원인: addSubview하는 순서에 대해 전혀 신경을 안쓰고 있었음.....

mainView.addSubview(activity)
mainView.addSubview(tableView)
mainView.addSubview(collectionView)

UIActivityIndicatorView를 맨 처음에 넣어주고

왜 화면에 안보이지??? 하고 있었따 =_=

해결 방법: addSubview로 할 때 UIActivityIndicatorView를 마지막에 쌓아줌!!!

내가 원하는 모양은

첨에 로딩 중일때

진짜 흰 화면 (테이블뷰 형태도 안보이고, 네비게이션 바도 안 보이는)을 원해서

다 Hidden 처리해줬다.

collectionView.isHidden = true
tableView.isHidden = true
self.navigationController?.isNavigationBarHidden = true

고민한 점: activity Indicator start를 어디서 해주고 finish를 어디서 해줘야 하는지?

데이타가 언제 다 받아와지는지를 모르는데 finish를 언제 해줘야 하는지 어케 알지?

임의로 타이머처럼 몇 초 세팅해놓고 finish하나?

let activity = UIActivityIndicatorView()
// 뷰를 일단 만들고

mainView.addSubview(tableView)
mainView.addSubview(collectionView)
mainView.addSubview(activity)
// 이렇게 하면 뷰가 스택처럼 차례대로 쌓인다.

self.activity.startAnimating()
// viewDidLoad에서 스타트

DispatchQueue.main.async {
	self.tableView.reloadData()
	self.collectionView.reloadData()
	self.activity.stopAnimating()
	self.tableView.isHidden = false
	self.navigationController?.isNavigationBarHidden = false
}
// 스탑은 viewDidAppear에서 각 뷰에 데이터를 모두 reload 해온 다음에 해줬다.
// 이때 숨겨놨던 tableView와 Navigation Bar 히든 처리 역시 모두 풀어준다.

49. UIActivityIndicatorView | SWIFT Tutorial | Learn SWIFT For Beginners | CodeWithHubbleApps |

[Swift] UIActivityIndicator 예제 (로딩중 표시 띄우기)

Apple Developer Documentation

How to hide a navigation bar from first ViewController in Swift?

문제점/고민한점 → 해결방안


문제점: 데이타가 안 불러와짐

원인: 위에서 items를 빈 배열의 변수로 선언해주고선

var items: [ItemInformation] = []

밑에 do catch문에서 items를 (메소드 안에서의) 지역 상수로 또 선언해줬다 ^.ㅠ

let items = apiResponse.items

해결 방법: let items를 self.items로 바꿔줌

self.items = apiResponse.items

Q. 여기서 self.items란?

A. 아직 인스턴스가 만들어지진 않았지만 앞으로 만들어질 그 인스턴스.items!!!

코다센세 URLSession 레슨

let dataTask: URLSessionDataTask = session.dataTask(with: url) { (data: Data?, response: URLResponse?, error: Error?)

총알 장전 단계

데이터 보내주세요!!!!

datatask.resume()
// 실제 데이터 요청하는 부분

GET에 한해서 필요한 것

1) url 주소

2) HTTP 메소드

3) HTTP 통신규약을 사용한다는 걸 알려줘야 함 (ver2)

2, 3번은 안해줘도 됨

why? swift에서는 (get을 워낙 많이 쓰니까) URLSession 쓰면 알아서 하도록 해줌!!

dataTask라는 인스턴스를 만들어줌

session.dataTask(with: url) 서버에 요청을 하겠다

컴퓨터 입장에서는 서버가 뭘 줄지 모르는 상황

우리는 알고 있으니까

받아왔을 때

받아온 데이터를 우리가 원하는 형식으로 바꿔주는 것

server → client한테 response 줄때

서버는 data, response, error를 줌

dataResponse를 다룰 수 있는 클로즈를

서버에서 이제 데이터 가져오면 실행함

session.dataTask

→ 어디가서 석유를 받아올래??

(목적지: url 주소)

받아왔을때

해줄 행위를

in ~ 뒤에 적어줌!

guard error == nil else { return }

guard error

에러 있으면 조기 탈출

아예 밖으로 나가버림

guard let statusCode = (response as? HTTPURLResponse)?.statusCode else { return }
let successRange = 200..<300
            
guard successRange.contains(statusCode) else { return }

정상적인 상태여야만 받겠다

guard let resultData = data else { return }

data 받아온게 실제로 값이 들어있냐?

있으면 넣어주고

아니면 가드문으로 탈출

let decoder = JSONDecoder()
let apiResponse = try decoder.decode(APIResponse.self, from: resultData)

디코드를 해서

apiResponse라는 걸 만들어줌

(실제 정제된 데이터가 됨)

= 우리가 원하는 형태의 휘발유가 됨

self.items = apiResponse.items

api 문서보면

page가 있고

items가 있었는데

우리가 전역으로 선언해준 items

→ 선언해준 클래스의 인스턴스의 변수 (items)를 넣어주겠다

정보가 제대로 있으면 self.items로 들어감


열정적인 코다센세의 줌 강의 현장 (a.k.a. 의존 모둠 질척대기)

URLSession은 비동기로 작동함!

Why? 서버에 갔다가 데이터 가져와서 제련하는 작업은 너무 오래 걸림

석유 가져오라고 배를 보내놓고

아무것도 안하고 있으면 너무 손실

(그동안에 다른 데 사업 계약도 하고 그래야함)

그래서 이 긴 과정을 따로 빼줌

→ 이게 비동기 처리

동기 = 같은 시간대에 이루어진다

비동기 = 따로 빼줬다

문제는

서버에 요청을 보내고

받아오는 동안

다른 일을 컴퓨터는 할건데

이때 화면을 그려버림

정보를 그려와서 화면을 그려줘야 하는데

그래야지 사진도 잘 뜨고

글자로 잘 뜨고 함

지금 이 과정에서는

서버에 요청을 하고

뭔가를 하고 있을때

화면을 이미 그려버림

(그래서 정보가 없는 상태니까

빈 셀만 보인 것)

DispatchQueue.main.async {
		self.tableView.reloadData()
}

(화면을 그려주는 일이라서 얘도 비동기로 처리해야 함 - 디스패치 async)

= 정보가 왔을 때 화면 다시 그리기를 실행한 것

(data부터는) 데이터를 받는 과정이 아니라 (이미 받아온 데이터를) 처리하는 과정이다 🌟

with: url까지는 요청 보내는 과정

completion handler에 해당하는 클로저 부터는 받아온 데이터를 처리하는 과정

우리가 코드에서 볼 수 있는 부분은 보내고 처리하는 부분만 알 수 있음

사진은 그냥 url = 문자열임

다 가져오긴 했는데 사진을 가져온게 아님

그래서 그 사진을 가지러 사진 주소로 다녀와야 함

코다센세 고마워요 👏👏👏

기타) 이미지를 불러오는 과정

DispatchQueue.main.async {
                        self.tableView.reloadData()
                        self.collectionView.reloadData()
                        self.activity.stopAnimating()
                        self.tableView.isHidden = false
                        self.navigationController?.isNavigationBarHidden = false
                    }
let imageURL: URL! = URL(string: item.thumbnails.first!)
guard let imageData: Data = try? Data(contentsOf: imageURL) else { return cell }
cell.itemThumbnail.image = UIImage(data: imageData)

뷰를 reload 해오는 작업 자체는 DispatchQueue에 비동기로 넣어줬지만

image를 불러오는 작업 자체는 동기 작업으로 해놓음.

제임스 실행 화면과 비교해봤을때

내 화면은 셀이나 이미지 삽입의 버벅거림도 없고

속도가 확실히 빠름

제임스 & 덕복의 의문

Q. 동기로 이미지를 받아오게 해놨는데 어떻게 속도가 저렇게 빠를까...?

이유는 나도 모름...

부끄럽지만 패스트 캠퍼스 강의에서 이렇게 하라고 알려줘서 그냥 그대로 보고 한거라 ^.ㅠ

흠... 이게 왜 더 빠른지도 모르겠다.

제임스 & 덕복 말로는

동기면 원래 느려야 하는데 (제대로 이해한게 맞나 ??)

그럼에도 버벅거림 없이 빠르게 이미지를 받아오는 이유는

지금은 상품 갯수가 20개 밖에 안되기도 하고

이미지 자체도 사이즈가 컨게 아니라서 그런게 아닐까 싶은데 ? 🤔

내일 PR 보낼 때 붱이한테

이 방식이 혹시 나중에 문제가 되는지 물어봐야겠다.

profile
iOS Developer

0개의 댓글