[스탠포드 iOS] 6강 멀티터치
6강 목표
- Gestures
Context, UIBezierPath
- Storyboard에 UIView를 하나 올리고 PlayingCardView 클래스와 연결시켜준다.
- 시스템이 해당 View를 drawing할 때 해당 코드 draw()를 사용한다.
- Context를 이용할 때 fillPath()가 나타나지 않고 UIBezierPath 구조체를 활용하면 문제를 해결할 수 있다.
- 가로로 회전했을 때 타원형으로 보이는 것을 볼 수 있다.
- Content Mode에서
Scale To Fill
에서Redraw
로 변경으로 문제 해결 가능
preferredFont & UIFontMetrics
- 사용자가 원하는 글자 크기를 선택할 수 있다.
- 해당 타입은 위의 블로그에서 참조했을 때
Dynamic Type
이다.
UIFont.systemFont(ofSize:weight:)
를 사용하면 Dynamic Type
을 지원할 수 없다.
Dynamic Type
이다.UIFont.systemFont(ofSize:weight:)
를 사용하면 Dynamic Type
을 지원할 수 없다.- 스토리보드에서는 Test Style 중 하나를 선택해야 한다.
강의
private func centeredAttributedString(_ string: String, fontSize: CGFloat) -> NSAttributedString {
var font = UIFont.preferredFont(forTextStyle: .body).withSize(fontSize)
font = UIFontMetrics(forTextStyle: .body).scaledFont(for: font) // 폰트 크기조절에 따론 폰트 설정
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
return NSAttributedString(string: string, attributes: [NSAttributedString.Key.paragraphStyle: paragraphStyle, .font: font])
}
// preferredFont(forTextStyle:)에 원하는 Text Style을 넣어준다.
// UIFontMetics는 Dynamic Type을 지원해줄 수 있다.(zeddios님의 블로그에 더 자세한 내용)
// 시뮬레이터에서 글자 크기를 변경했다고 해서 바로 적용이 되지 않는 문제가 발생했다.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
setNeedsDisplay()
setNeedsLayout()
}
// 해당 메소드를 사용해주면 글자 크기를 변경할 때마다 바로 적용이 된다.
setNeedsDisplay & setNeedsLayout
setNeedsDisplay
- 과정
- View 업데이트 필요성 발생
- 직접
draw(_ rect:)
메소드를 호출하지 않는다.
setNeedsDisplay()
를 호출해야 한다.
- 다음 drawing cycle에 업데이트
- View 업데이트
setNeedsLayout
layoutSubViews()
: SubView들을 배치한다.
- 위의 메소드도 직접 호출하면 안 된다. 그래서 업데이트를 해주려면 setNeedsLayout()를 호출해줘야 한다. 위의 과정과 비슷하다.
constraints priority
- View 업데이트 필요성 발생
- 직접
draw(_ rect:)
메소드를 호출하지 않는다. setNeedsDisplay()
를 호출해야 한다.- 다음 drawing cycle에 업데이트
- View 업데이트
layoutSubViews()
: SubView들을 배치한다.- 전체적으로 Safe Area 모서리 부분에 16의 범위를 줘서 넘어가지 않도록 했다.
- 강의에서 원하는건 해당 핸드폰에서 5:8의 비율로 가장 큰 카드 모양을 만들고 싶었다.
- 특이했던건 Width를 800으로 놔뒀는데 이 자체가 범위를 넘어가는 범위라서 오류가 발생한다.
- 하지만 Priority를 1000(Required)에서 750(High)로 수정해줌으로써 오류가 발생하지 않았다.
- 중요하지 않은 제한 조건의 우선 순위를 낮게 놔둔다.
UISwipeGestureRecognizer
@IBOutlet weak var playingCardView: PlayingCardView! {
didSet {
let swipe = UISwipeGestureRecognizer(target: self, action: #selector(nextCard))
swipe.direction = [.left, .right]
playingCardView.addGestureRecognizer(swipe)
}
}
@objc func nextCard() {
if let card = deck.draw() {
playingCardView.rank = card.rank.order
playingCardView.suit = card.suit.rawValue
}
}
// 스토리보드 @IBOutlet을 사용하는 방법이다.
// 주로 didSet을 활용해서 view에게 동작하도록 만든다.
// swipe 방향을 왼쪽, 오른쪽으로 설정
@IBOutlet weak var playingCardView: PlayingCardView! {
didSet {
let swipe = UISwipeGestureRecognizer(target: self, action: #selector(nextCard))
swipe.direction = [.left, .right]
playingCardView.addGestureRecognizer(swipe)
}
}
@objc func nextCard() {
if let card = deck.draw() {
playingCardView.rank = card.rank.order
playingCardView.suit = card.suit.rawValue
}
}
// 스토리보드 @IBOutlet을 사용하는 방법이다.
// 주로 didSet을 활용해서 view에게 동작하도록 만든다.
// swipe 방향을 왼쪽, 오른쪽으로 설정
- 좌, 우로 스와이프 시 새로운 카드 등장
UITapGestureRecognizer
- Tap Gesutre Recognizer 를 추가해주고 @IBAction 메소드 추가
@IBAction func flipCard(_ sender: UITapGestureRecognizer) {
switch sender.state {
case .ended:
playingCardView.isFaceUp = !playingCardView.isFaceUp
default:
break
}
}
UIPinchGestureRecognizer
// PlayingCardView.swift
var faceCardScale: CGFloat = SizeRatio.faceCardImageSizeToBoundsSize {
didSet {
setNeedsDisplay()
}
}
@objc func adjustFaceCardScale(byHandlingGestureRecognizedBy recognizer: UIPinchGestureRecognizer) {
switch recognizer.state {
case .changed, .ended:
faceCardScale *= recognizer.scale
recognizer.scale = 1.0
default:
break
}
}
// ViewController.swift
@IBOutlet weak var playingCardView: PlayingCardView! {
didSet {
let pinch = UIPinchGestureRecognizer(target: playingCardView, action: #selector(playingCardView.adjustFaceCardScale(byHandlingGestureRecognizedBy:)))
playingCardView.addGestureRecognizer(pinch)
}
}
// PlayingCardView.swift
var faceCardScale: CGFloat = SizeRatio.faceCardImageSizeToBoundsSize {
didSet {
setNeedsDisplay()
}
}
@objc func adjustFaceCardScale(byHandlingGestureRecognizedBy recognizer: UIPinchGestureRecognizer) {
switch recognizer.state {
case .changed, .ended:
faceCardScale *= recognizer.scale
recognizer.scale = 1.0
default:
break
}
}
// ViewController.swift
@IBOutlet weak var playingCardView: PlayingCardView! {
didSet {
let pinch = UIPinchGestureRecognizer(target: playingCardView, action: #selector(playingCardView.adjustFaceCardScale(byHandlingGestureRecognizedBy:)))
playingCardView.addGestureRecognizer(pinch)
}
}
링크
- edwith : [스탠포드] Swift를 활용한 iOS11 앱 개발
- zeddiOS - preferredFont와 UIFontMetrics
- zeddiOS - View/레이아웃 업데이트 관련 메소드
Author And Source
이 문제에 관하여([스탠포드 iOS] 6강 멀티터치), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@hhhan0315/스탠포드-iOS-6강-멀티터치
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Author And Source
이 문제에 관하여([스탠포드 iOS] 6강 멀티터치), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@hhhan0315/스탠포드-iOS-6강-멀티터치저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)