19 Aug 2021
|
iOS
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
tableView
setHighlighted
셀의 강조 표시된 상태를 설정하고 선택적으로 상태 간 전환 애니메이션을 실행
func setHighlighted(_ highlighted: Bool, animated: Bool)
- highlighted: 셀을 강조 표시로 설정하려면 true, 아니면 false > default: false
쉽게말하면 셀을 터치했을때 화면의 섹이 살짝 바뀌는것을 볼수있다.
사용자가 셀을 선택했는지 안했는지를 확인해볼 수 있음. > 사용자 관점에서 좀더 편리하다는 장점이 있다.
개발자적 관점에서는 무엇을 터치했을때 에러가 발생했는지 조금더 직관적으로 볼 수 있다는 장점이 있을 듯 하다….
특정 섹션의 헤더뷰 높이 지정
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int)
특정 섹션의 푸터뷰 높이 지정
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int)
위 두개를 보통 사용하는건 이러한 예시가 있다.
테이블뷰의 타입을 그룹으로 했을때 기본적으로 섹션의 자동 높이가 설정되어 뷰에 나타나게 된다.
그러나 나는 그 섹션의 높이가 마음에 안들거나 조절을 해야하는 경우가 있을텐데, 그때 이 delegate를 사용해준다.
특정 섹션의 헤더뷰 요청
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int)
특정 섹션의 푸터뷰 요청
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int)
collectionView
지정된 항목이 표시될 때까지 collectionView 스크롤
func scrollToItem(at indexPath: IndexPath, at scrollPosition: UICollectionView.ScrollPosition, animated: Bool)
- indexPath: 스크롤할 뷰 항목의 인덱스 경로
- scrollPosition: 스크롤 완료될 때 항목이 배치되어야 하는 위치
- animated: 스크롤 동작 적용하려면 true, 스크롤 뷰의 내용을 즉지 조정하려면 false
예제 블로그를 통해 확인해보면
스크롤뷰가 스크롤 되는 동안 계속 호출되는 delegate라고 한다.
스크롤 뷰의 드래그가 끝나기 직전에 델리게이트에 알림
optional func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>)
간단한 예시로 생각해보자.
테이블 뷰 안에 컬렉션 뷰가 있다고 생각해보자.
테이블 뷰 중간에 컬렉션 뷰가 있었고, 컬렉션 뷰의 셀을 스크롤 해놓은 상태에서 > index가 0이 아닌상태에서
테이블뷰를 아래로 스크롤했다고 생각해보자.
이때 다시 해당 컬렉션뷰로 돌아갔을때, 컬렉션 뷰의 컨텐트 인덱스는 과연 어디에 위치해 있을까?
이를 정해주는 delegate이다.
말 그대로 사용자가 스크롤을 하고 스크린과 손이 떨어졌을때 호출되는 메소드이다.
이를 통해 스크롤할 때 컨텐트의 위치를 조정하여 페이징되는 효과를 낼 수 있다.
예제 블로그 < 요 블로그 예제를 보면 이해가 쉬울 것 같다.
가로 스크롤 바 표시 여부를 제어하는 부울 값
var showsHorizontalScrollIndicator: Bool { get set }
isPagingEnabled
페이징을 사용할 수 있는 여부를 결정하는 부울 값
var isPagingEnabled: Bool { get set }
19 Aug 2021
|
iOS
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
Dispatch Queue
dispatchQueue 라는 객체는 메인 스레드나 백그라운드 스레드에서 업무를 직렬이나 병렬적으로 수행하도록 한다.
큐에 업무를 보낼때, 백그라운드 큐에 넣으면 시스템이 알아서 수행해준다. 그런데 각 테스크가 어떤 스레드에 의해 수행되는지는 알수가 없다. 직접 구현해야하는 부분은 동기/비동기적으로 테스크가 수행할 수 있도록 하는 것. 이때 중요한 점은 메인스레드에서는 데드락 이슈로 인해 동기적인 처리를 하지는 않아야 한다.
- 동기: 하나의 테스크가 끝나야 그 다음 테스크 진행
- 비동기: 여러 테스크가 동시에 진행
이때 중요한 것은 스레드를 생성할 수 있는 갯수의 한계는 존재하기 때문에, dispatchQueue는 너무 많이 만들면 안된다.
- 직렬: 하나씩 차례대로 테스크 전달
- 병렬: 한번에 여러개의 테스크 전달
Dispatch Group
서로 다른 테스크들을 그룹화하여 테스크들이 완료될때까지 기다리거나 완료되면 알림을 받을 수 있도록 하는 것
여러작업을 하나로 묶는 것. 따라서 그룹에 포함된 모든 작업이 완료되어야 그룹이 완료된다.
사용 방법
- 테스크를 위해 concurrent queue를 생성
- 각각의 테스크를 묶을 수 있는 DispatchGroup를 생성
- 각각의 테스크들을 queue에 담을 때 .enter() 호출
- 각 테스크의 완료 시점에 .leave()를 호출
- .notify를 통해 완료 이벤트의 알림을 받고 각각의 테스크가 다 끝난 후 필요한 작업을 진행
let myQueue = dispatchQueue(label: "com.nil.work", attribute: .concurrent)
let myGroup = DispatchGroup()
myGroup.enter()
myQueue.async {
for i in 1...10 {
print("\(i), 가")
}
myGroup.leave()
}
myGroup.enter()
myQueue.async {
for i in 100...105 {
print("\(i), aaaa")
}
myGroup.leave()
}
myGroup.notify(queue: myQueue) {
print("end...")
}
- .enter()는 myGroup에 테스크를 포함시키는 것을 의미
- .leave()는 DispatchGroup에 해당 테스크가 완료되었다고 알려주는 의미
enter와 leave는 서로 쌍을 이루어야 한다!!
19 Aug 2021
|
iOS
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
@discardableResult
버릴수 있는 결과 라는 뜻으로 말 그대로 스위프트에서는 개발자를 위해 여러가지 warning들을 띄워준다.
- 값이 변하지 않으면 var가 아닌 let을 사용하세요
- 변수가 사용되지 않았으니 _ 를 사용해세요
등등…
이와 마찬가지로 Result of vall to ~~ is unused 와 같이 결과 값이 사용되지 않았습니다. 라는 워닝도 있다.
그러나 결과를 return 하는데 이 결과가 필요 없는 경우도 있을것! 그럴때 warning을 보고싶지않다? 이럴때 사용한다.
@discardableResult
func log (_ msg: String) -> String {
return "\(msg) is enetered"
}
즉, @discardableResult 는 결과와 관계없이 warning을 띄워주지마! 라는 의미를 가진다.
18 Aug 2021
|
iOS
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
Tableview Swipe
UITableview의 delegate를 상속하는 뷰컨에서 Swipe를 입력하면 leading, trailing으로 시작하는 메소드가 있다.
말 그대로 leading은 왼쪽 끝에서 보이게 될 swipe action이고 trailing는 오른쪽 끝에서 보이게 될 swipe action이다.
이 swipe action을 구현하기 위해서는 UIContextualAction 과 UISwipeActionsConfiguration 을 만들어줘야한다.
UIContextualAction
테이블 로우를 스와이프 했을 때 보여지는 액션
이를 사용하기 위해서는 UITableview delegate에 UISwipeActionsConfiguration을 초기화 해야한다.
UISwipeActionsConfiguration
테이블 뷰의 로우를 스와이프 했을 때 작동할 액션들의 set
테이블 뷰 로우의 커스텀 스와이프 액션들을 모아둔 객체를 의미한다.
직접 구현해보기(leading)
- UIContextualAction을 만들어서 UISwipeActionsConfiguration에 담아 return
func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let actions1 = UIContextualAction(style: , title: , handler: )
return UISwipeActionsConfiguration(actions: )
}
- UIContextualAction.style: enum 타입으로 normal 와 destructive 가 있다.
- UIContextualAction.handler: action, sourceView, completionHandler를 파라미터로 갖는 handler
func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let actions1 = UIContextualAction(style: .normal, title: "1", handler: { action, view, completionHaldler in
print("action performed")
completionHaldler(true)
})
return UISwipeActionsConfiguration(actions: [actions1])
}
직접 구현해보기(trailing)
leading과 구현방식은 같지만, UISwipeActionsConfiguration의 actions에 UIContextualAction를 담는 순서에 따라 보여지는게 반대이다.
func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let actions1 = UIContextualAction(style: .normal, title: "1", handler: { action, view, completionHaldler in
print("action1 performed")
completionHaldler(true)
})
let actions2 = UIContextualAction(style: .normal, title: "2", handler: { action, view, completionHaldler in
print("action2 performed")
completionHaldler(true)
})
return UISwipeActionsConfiguration(actions: [actions1, actions2])
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let actions1 = UIContextualAction(style: .normal, title: "1", handler: { action, view, completionHaldler in
print("action1 performed")
completionHaldler(true)
})
let actions2 = UIContextualAction(style: .normal, title: "2", handler: { action, view, completionHaldler in
print("action2 performed")
completionHaldler(true)
})
return UISwipeActionsConfiguration(actions: [actions1, actions2])
}
- leading swipe title > 1, 2
- trailing swipe title > 2, 1
즉, 같은 순서로 액션들을 담았음에도 불구하고 반대방향으로 배치되어 나온다.
leading메소드는 UISwipeActionsConfiguration에서 action을 꺼내 leading쪽부터 데이터를 밀어넣고
trailing메소드는 UISwipeActionsConfiguration에서 action을 꺼내 trailing쪽부터 즉, 서로 반대방향으로 밀어넣는다고 생각하면 쉽다.
View 꾸며보기
swipe action의 버튼 이미지 혹은 색상을 입히는 방법이다.
func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let actions1 = UIContextualAction(style: .normal, title: "1", handler: { action, view, completionHaldler in
print("action1 performed")
completionHaldler(true)
})
actions1.backgroundColor = .systemOrange
actions1.image = UIImage(named: "comment.png")
let actions2 = UIContextualAction(style: .normal, title: "2", handler: { action, view, completionHaldler in
print("action2 performed")
completionHaldler(true)
})
actions2.backgroundColor = .systemYellow
actions2.image = UIImage(named: "share.png")
return UISwipeActionsConfiguration(actions: [actions1, actions2])
}
이렇게 UIContextualAction변수를 생성하고나서 적용해주면 된다.
이때 주의해야할 점은 swipe action view 영역에 맞는 이미지 크기여야 한다!
17 Aug 2021
|
iOS
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
UIResponder
리스폰더 객체, 즉 UIResponder의 인스턴스는 UIKit 앱 이벤트 처리 백본을 구성한다.
많은 핵심 객체는 UIApplication객체 및 모든 UIView객체(UIWindow포함)를 포함하여 리스폰더이다.
즉, UIApplication, UIViewController, UIView 객체 모두 리스폰더라는 이야기이다.
이벤트가 발생하면, UIKit는 이를 처리할 수 있도록 앱의 리스폰더 객체에 전달한다.
이는 또 다시말하면, 이벤트가 발생하면 UIApplication, UIViewController, UIView객체가 해당 이벤트를 다룰 수 있다는 의미다.
이벤트에는 터치 이벤트, 모션이벤트, 원격제어 이벤트 및 press이벤트를 비롯한 여러 종류의 이벤트가 존재한다. 특정 타입의 이벤트를 처리하려면, 리소폰더가 해당 메소드를 오버라이드 해야한다.(To handle a specific type of event, a responder must override the corresponding methods) 예를들어 터치이벤트를 처리하기 위해 리스폰더는 touchesBegan(_:with), touchesMoved(_:with), touches Ended(_:with), touchedCancelled(_:with)
를 구현해야한다. 이렇게 터치이벤트의 경우 리스폰더는 UIKit에서 제공한 이벤트 정보를 사용해 해당 터치의 변경사항을 추적하고, 앱의 인터페이스를 적절하게 업데이트 해야한다.
이벤트 처리 외에도 UIKit 리스폰더는 처리되지 않은 앱의 다른 부분을 전달하는 작업을 관리한다.
주어진 리스폰더가 이벤트를 처리하지 않으면, 리스폰더 체인의 다음 이벤트로 해당 이벤트를 전달한다. UIKit는 미리 정의된 규칙을 사용해 리스폰더 체인을 동적으로 관리하여 어떤 객체가 이벤트를 수신한 다음에 어떤 객체를 선택할지 결정한다. 예를들어, 뷰는 이벤트를 상위 뷰로 전달하고, 계층의 루트 뷰는 이벤트를 해당 뷰컨으로 전달한다.