Skip to content

Latest commit

ย 

History

History

CHAPTER5

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
ย 
ย 
ย 
ย 

Contents

Thrown Errors

๋งจ ๋’ค์— throws ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์—ฌ์„œ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

func save() throws

throws ๊ฐ€ ๋ถ™์€ ํ•จ์ˆ˜๋Š” ์—๋Ÿฌ๋ฅผ ๋˜์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋˜์ ธ์ง„ ์—๋Ÿฌ๋ฅผ ์žก์•„์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

do-catch

do-catch ๊ตฌ๋ฌธ์œผ๋กœ throws ํ•จ์ˆ˜๋ฅผ ์ฒ˜๋ฆฌํ•ด์ค๋‹ˆ๋‹ค. ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์ง€๋งŒ ํ•œ๋ฒˆ ์‹คํ–‰ํ•ด๋ณธ๋‹ค๋Š” ์˜๋ฏธ๋กœ ํ•จ์ˆ˜ ์•ž์— try ๋ฅผ ๋ถ™์—ฌ์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด catch ๊ตฌ๋ฌธ์œผ๋กœ ๊ฐ€๊ณ  Error ํ”„๋กœํ† ์ฝœ์˜ ๊ตฌํ˜„์ฒด NSError ๋„ ํ•จ๊ป˜ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

do {
	try context.save()
} catch let error {
	// ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ด๊ณณ์œผ๋กœ ๋‚ ๋ผ์˜จ๋‹ค.
  // let error๋Š” ๋ฐœ์ƒํ•œ error์˜ ์ง€์—ญ๋ณ€์ˆ˜๋กœ Error protocl์˜ ๊ตฌํ˜„์ฒด์ด๋‹ค.
}

try!

do-catch ๊ตฌ๋ฌธ์ด ์‹ซ๋‹ค๋ฉด, try! ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋Š”๋ฐ, ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์•ฑ์„ ๊ฐ•์ œ ์ข…๋ฃŒ์‹œํ‚ต๋‹ˆ๋‹ค. ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ™•์‹ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰ ์ž˜ ์“ฐ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

try! context.save()

try?

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ do-catch ๊ฐ€ ์‹ซ๊ณ  ์‹ฌ๊ฐํ•˜์ง€ ์•Š์€ ์—๋Ÿฌ๋ผ๋ฉด, ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ try? ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์•ฑ์„ ๋ฉˆ์ถ”์ง€ ๋ง๊ณ  ์—๋Ÿฌ๋ฅผ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด optional๋กœ ๋ฐ”๊ฟ”์„œ ๋ฆฌํ„ดํ•ด์ค๋‹ˆ๋‹ค. ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์œผ๋ฉด ๊ฐ’์„ ์ฃผ๊ณ  ์•„๋‹ˆ๋ผ๋ฉด nil์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

let x = try? errorProneFunctionThatReturnsAnInt() // x: Int?

Any & AnyObject

Any ํƒ€์ž…๊ณผ ๋™์ผํ•œ AnyObject ๋ผ๋Š” ํƒ€์ž…๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ž˜์Šค ํƒ€์ž…์— ํ•œํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” any๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์—ญ์‹œ swift ์ž…์žฅ์—์„  ๋‹ฌ๊ฐ‘์ง€ ์•Š์€ ๋…€์„์œผ๋กœ any์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Objective-C ์™€์˜ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด์„œ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

Objective-C์—๋Š” id ๋ผ๋Š” ์ค‘์š”ํ•œ ํƒ€์ž…์ด ์žˆ๋Š”๋ฐ, id๋Š” ์–ด๋–ค ๊ฒƒ๋„ ๋  ์ˆ˜ ์žˆ๊ณ  ๊ฑฐ์˜ ๋ชจ๋“  api์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

Any ํƒ€์ž… ๋ณ€์ˆ˜๋Š” ๊ตฌ์กฐ์ฒด, ์—ด๊ฑฐํ˜•, ํด๋ž˜์Šค ๋“ฑ ๋‹ค์–‘ํ•œ ํƒ€์ž…์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

as

Any ํƒ€์ž…์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์•„๋Š” ํƒ€์ž…์œผ๋กœ ๋ฐ”๊ฟ”์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ as? ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ํƒ€์ž…์„ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ๋ฐ”๊ฟ”์ฃผ๊ณ  ์•„๋‹ˆ๋ผ๋ฉด nil์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ as? ๋กœ ๋ณ€ํ™˜์‹œ์ผœ์ฃผ๋ฉด Optional ํƒ€์ž…์ด ๋ฉ๋‹ˆ๋‹ค.

let unknown: Any
if let foo = unknown as? MYType {
  // foo: Mytype
}

Casting

as๋Š” Any ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ํƒ€์ž…์—๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฃผ๋กœ ์ƒ์œ„ ํด๋ž˜์Šค ํ•˜์œ„ ํด๋ž˜์Šค๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ downcasting ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. class ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ protocol ์—๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

let vc: UIViewController = ConcentrationViewController()
if let cvc = vc as? ConcentrationViewContrller {
  cvc.flipCard(...)	// UIViewController๊ฐ€ ์•„๋‹Œ ConcentrationViewController์˜ ๋ฉ”์†Œ๋“œ
}

Other Interesting Classes

NSObject

NSObject๋Š” ๋ชจ๋“  objective-c ํด๋ž˜์Šค์˜ root ํด๋ž˜์Šค ์ž…๋‹ˆ๋‹ค.

UIViewController ๊ฐ™์€ UIKit์˜ ๋ชจ๋“  ํด๋ž˜์Šค๊ฐ€ Objective-C ์—์„œ ๊ฐœ๋ฐœ๋˜์—ˆ๋Š”๋ฐ, ์—ฌ์ „ํžˆ Objective-C์™€ ํ˜ธํ™˜์ด ๊ฐ€๋Šฅํ•˜๊ณ  ์ด ํด๋ž˜์Šค๋“ค์ด ๋ชจ๋‘ NSObject ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Objective-C ์—์„œ๋Š” NSObject ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์ง€ ์•Š์œผ๋ฉด ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€๋งŒ, Swift ์—์„œ๋Š” NSObject ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์„ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๋‹จ, ๋ช‡๋ช‡ ์†Œ์ˆ˜์˜ API ๋“ค์ด NSObject ํด๋ž˜์Šค๋ฅผ ์š”๊ตฌํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

NSNumber

Objective-C ์—์„œ๋Š” ์ˆซ์ž๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ์ด Class๋ฅผ ์ด์šฉํ•ฉ๋‹ˆ๋‹ค. Swift์—์„œ๋Š” Double ์ด๋‚˜ Int๋Š” Struct์ด๊ธฐ ๋•Œ๋ฌธ์— ํด๋ž˜์Šค๊ฐ€ ์—†์ง€๋งŒ, Objective-C ์—๋Š” ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

๊ฐ์ฒด์ง€ํ–ฅ ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด NSNumber ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. NSNumber๋Š” ์†Œ์ˆ˜๋‚˜ ์ •์ˆ˜ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ Boolean ๊นŒ์ง€๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

iOS์—์„œ ๋งŽ์€ API๊ฐ€ NSNumber ํด๋ž˜์Šค๋ฅผ ์ทจํ•˜์ง€๋งŒ, ์ž๋™์œผ๋กœ Swift ํƒ€์ž…์œผ๋กœ bridge ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ NSNumber ๋”ฐ๋กœ ์•Œ ํ•„์š”๋Š” ์—†๊ณ  Swift์—์„œ NSNumber๋กœ ๋ญ”๊ฐ€๊ฐ€ ๋‚ ๋ผ์™”๋”๋ผ๋„ ๊ทธ๋ƒฅ ์–ด๋–ค ํƒ€์ž…์œผ๋กœ ์ƒ๊ฐํ•ด๋„ ๋ฌด๋ฐฉํ•ฉ๋‹ˆ๋‹ค.

let n = NSNumber(35.5) or let n: NSNumber = 35.5
let intified: Int = n.intValue // or doubleValue, boolValue, etc ...
let boolean: Bool = n.boolValue // true

Date

Date๋Š” ๋‚ ์งœ๋‚˜ ์‹œ๊ฐ„์„ ํ‘œํ˜„ํ•˜๋Š” ํƒ€์ž…์ž…๋‹ˆ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” 1970๋…„ ์ดํ›„๋กœ ๋ช‡ ์ดˆ๊ฐ€ ํ˜๋ €๋Š”์ง€ ํ‘œํ˜„๋˜๊ณ , ์•„์ฃผ ์ •๋ฐ€ํ•œ ๋‹จ์œ„๋กœ ๋ฐฑ๋งŒ๋ถ„์˜ 1์ดˆ ๋‹จ์œ„๋กœ ์ธก์ •ํ•ฉ๋‹ˆ๋‹ค.

Calendar, DateFormatter, DateComponents ๋“ฑ์˜ ํด๋ž˜์Šค๊ฐ€ ์ข…์ข… ํ•จ๊ป˜ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด Date๋ฅผ ๊ณง๋ฐ”๋กœ UI์„ ๋•Œ๋Š” ๋งค์šฐ ์กฐ์‹ฌํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๊ธฐ ๋–„๋ฌธ์ž…๋‹ˆ๋‹ค. ์ „ ์„ธ๊ณ„์—์„œ ๋‚ ์งœ๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค.

Data

Data๋Š” bit๊ฐ€ ๋‹ด๊ฒจ์žˆ๋Š” ๊ฐ€๋ฐฉ์ž…๋‹ˆ๋‹ค. iOS API ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ธํ„ฐ๋„ท์˜ ์–ด๋–ค URL์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์–ป๊ณ  ์‹ถ๋‹ค๋ฉด bit ๊ฐ€๋ฐฉ์ธ Data๋ฅผ ํ™•์ธํ•ด์„œ ์›ํ•˜๋Š” UIImage ๋“ฑ์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ JSON ๋“ฑ์œผ๋กœ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Data๋Š” ๊ทธ์ € bit ๊ฐ€๋ฐฉ์ด๋ฏ€๋กœ ์›ํ•˜๋Š” ํ˜•ํƒœ๋กœ ๊บผ๋‚ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. bit๋ฅผ ๋‹ค์–‘ํ•œ ํด๋ž˜์Šค๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋Š” ๋ฉ”์†Œ๋“œ๋“ค์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

Views

View ๋Š” ๋‘ ๊ฐ€์ง€ ์˜๋ฏธ๋กœ ํ•ด์„๋ฉ๋‹ˆ๋‹ค.

  1. MVC ์˜ V ๋กœ ViewController์— ๋ถ™์–ด์žˆ๋Š” ๋งŽ์€ view ๋“ค์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

  2. iOS์˜ ํด๋ž˜์Šค์ธ UIVIew์˜ ์„œ๋ธŒ ํด๋ž˜์Šค๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

UIView์˜ Subclass

UIView์˜ ์„œ๋ธŒ ํด๋ž˜์Šค๋Š” ์ขŒํ‘œ๊ณ„๋ฅผ ์ •์˜ํ•˜๋Š” ํ™”๋ฉด์˜ ์ง์‚ฌ๊ฐํ˜•์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ์ด ์ขŒํ‘œ๊ณ„๋Š” drawing ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๊ณ  ์†๊ฐ€๋ฝ์„ ์ด์šฉํ•ด ๋ฉ€ํ‹ฐํ„ฐ์น˜๋ฅผ ํ•  ๋•Œ์—๋„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Hierarchical

์ง์‚ฌ๊ฐํ˜• ์•ˆ์— ์ง์‚ฌ๊ฐํ˜•, ์ฆ‰ View ์•ˆ์— View๊ฐ€ ์žˆ๋Š” ๊ณ„์ธต ๊ตฌ์กฐ(Hierarchical)๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค. View๋Š” ๊ทธ View๊ฐ€ ์†ํ•ด์žˆ๋Š” ํ•˜๋‚˜์˜ Superview๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—†์„ ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— UIView? ํƒ€์ž…์ด ๋ฉ๋‹ˆ๋‹ค. ๋˜ View๋Š” ๋งŽ์€ Subviews๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

var superview: UIView?
var subviews: [UIView]

UIWindow

View ๋“ค์˜ ์ตœ์ƒ์œ„์— UIWindow๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค. iOS ์•ฑ์—์„œ ๋”ฑ ํ•˜๋‚˜๋งŒ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์—ญ์‹œ View์ด๋ฏ€๋กœ UIView์˜ ์„œ๋ธŒํด๋ž˜์Šค ์ž…๋‹ˆ๋‹ค.

View Hierarchy

View์˜ ๊ณ„์ธต ๊ตฌ์กฐ๋Š” xcode์˜ storyboard ๊ฐ™์€ interface builder ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, code๋กœ๋„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถ”๊ฐ€ํ•  ๋•Œ๋Š” ์ƒ์œ„ ๋ทฐ์— func addSubview(_ view: UIView) ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ํ•˜์œ„ ๋ทฐ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ œ๊ฑฐํ•  ๋•Œ๋Š” ํ•˜์œ„ ๋ทฐ ์— func removeFromSuperview() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์ƒ์œ„ ๋ทฐ์—์„œ ํ•˜์œ„ ๋ทฐ๋ฅผ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

var superView = UIView()
var secondView = UIView()
var thirdView = UIView()

supverView.addSubview(subView)
subView.addSubview(thirdView)
/*
superView
	๏พค subView
		๏พค thridView
*/
thridView.removeFromSuperview()
/*
superView
	๏พค subView
*/

ViewController ์—์„œ var view: UIView ๊ฐ€ view์˜ ์ตœ์ƒ์œ„์— ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค.

Intializing a UIView

๋ณดํ†ต ๊ฐ€๋Šฅํ•˜๋ฉด initializing๋Š” ํ”ผํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฐฉ๋ฒ•์„ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๋ฉด ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ทฐ์—๋Š” ๋ณดํ†ต ๋‘ ์ข…๋ฅ˜์˜ initialze๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

  • init(frame: CGRect) // ์ฝ”๋“œ๋กœ ์ƒ์„ฑํ•  ๋•Œ

  • init(coder: NSCoder) // interface builder(์Šคํ† ๋ฆฌ๋ณด๋“œ)๋กœ ์ƒ์„ฑํ•  ๋•Œ

    NSCoder๋ผ๋Š” coder๋Š” ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋”๋ฅผ ์ž ์‹œ ์ค‘๋‹จ์‹œ์ผฐ๋‹ค๊ฐ€ ์•ฑ์ด ์‹คํ–‰๋˜๋ฉด ๋‹ค์‹œ ์‚ด๋ ค๋‚ด๋Š” ๋งค์ปค๋‹ˆ์ฆ˜์„ ๊ฐ–๊ณ  ์žˆ๋Š” ํ”„๋กœํ† ์ฝœ์ž…๋‹ˆ๋‹ค.

์ด ๋‘ ๊ฐ€์ง€๋ฅผ ๋ชจ๋‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์™œ๋ƒํ•˜๋ฉด frame๊ณผ ํ•จ๊ป˜ ์“ฐ์ด๋Š” init์€ ์ง€์ •๋œ ์ด๋‹ˆ์…œ๋ผ์ด์ €๋ผ์„œ ์ฝ”๋“œ์—์„œ ๋ทฐ๋ฅผ ์ƒ์„ฑํ•œ ๋’ค ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

coder์™€ ํ•จ๊ป˜ ์“ฐ์ด๋Š” Init์€ UIView๊ฐ€ NSCoder ํ”„๋กœํ† ์ฝœ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

setup๊ณผ ๊ฐ™์€ ๊ณตํ†ต ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ  ๋‘ ๊ฒฝ์šฐ์— ๋ชจ๋‘ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ ๋ณ€์ˆ˜๋Š” super.init์„ ์ „์— ๋ชจ๋‘ ์ดˆ๊ธฐํ™”๊ฐ€ ๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ, setup ์•ˆ์—์„œ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋ฏธ๋ฆฌ ์ดˆ๊ธฐํ™”๊ฐ€ ๋˜์–ด์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

func setup() { ... }

override init(frame: CGRect) {
	super.init(frame: frame)
	setup()
}

required init?(coder aDecoder: NSCoder) {
	super.init(coder: aDecoder)
	setup()
}

UIView๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ awakeFromNib()๋ฅผ ์“ฐ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. awakeFromNib()๋Š” ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋”์—์„œ ๋‚˜์˜จ ๋ชจ๋“  ์˜ค๋ธŒ์ ํŠธ์—๊ฒŒ ๋ณด๋‚ด์ง‘๋‹ˆ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋” ํŒŒ์ผ์—์„œ ๋‚˜์˜จ ๋ทฐ๋งŒ awakeFromNib๊ฐ€ ํ˜ธ์ถœ๋˜๋Š”๋ฐ, ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋”๊ฐ€ ๋‹ค์‹œ ์‚ด์•„๋‚ฌ์„ ๋•Œ, ์ฆ‰ ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋”์˜ ์ค‘๋‹จ์ด ํ•ด์ œ๋˜์—ˆ์„ ๋•Œ๋งŒ awakeFromNib๊ฐ€ ํ˜ธ์ถœ ๋ฉ๋‹ˆ๋‹ค. frame ์„ ์‚ฌ์šฉํ•ด ์ƒ์„ฑ๋œ View์—์„œ๋Š” ์ด ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Nib๋Š” ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋” ํŒŒ์ผ์˜ ์˜›๋‚  ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. Ib์™€ Nib๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋”๋ฅผ ๋œปํ•ฉ๋‹ˆ๋‹ค.

Coordinate System Data Structures

ํ™”๋ฉด์— ๋ทฐ๋ฅผ ๊ทธ๋ฆฌ๊ธฐ์— ์•ž์„œ ๋จผ์ € ๊ธฐ๋ณธ์ ์œผ๋กœ ์•Œ์•„์•ผ ํ•  ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋ฐฐ์›Œ๋ณผ ์ฐจ๋ก€์ž…๋‹ˆ๋‹ค.

์•ž์— ๋ชจ๋‘ CG๊ฐ€ ๋ถ™๋Š”๋ฐ CG๋Š” Core Graphics ๋ฅผ ๋œปํ•ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ iOS์—์„œ ์ฝ”์–ด ๊ทธ๋ž˜ํ”ฝ์Šค๋Š” 2์ฐจ์› ๋“œ๋กœ์ž‰์„ ํ•˜๊ธฐ ์œ„ํ•œ ์‹œ์Šคํ…œ์„ ๋œปํ•ฉ๋‹ˆ๋‹ค.

์ฝ”์–ด ๊ทธ๋ž˜ํ”ฝ์Šค๋Š” 4๊ฐœ์˜ ํƒ€์ž…์„ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

CGFloat

๋“œ๋กœ์ž‰์€ ๋ถ€๋™ ์†Œ์ˆ˜์  ์ˆซ์ž๋ฅผ ์ขŒํ‘œ๋กœ ํ•˜๋Š” ์‹œ์Šคํ…œ์—์„œ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. ๋ทฐ์˜ ์ขŒํ‘œ ์‹œ์Šคํ…œ์—์„œ ์ •์ˆ˜๋‚˜ Double, Float์ด ์•„๋‹Œ CGFloat์ด ๊ธฐ๋ณธ ์ขŒํ‘œ๊ฐ’์ด ๋ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  CGFloat์—๋„ initializer๊ฐ€ ์žˆ์–ด์„œ Double ์ด๋‚˜ Float ์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

let cgf = CGFloat(aDouble)

CGPoint

CGFloat ํƒ€์ž…์ธ ๋ณ€์ˆ˜ x, y ๊ฐ€ ๋“ค์–ด์žˆ๋Š” ๊ตฌ์กฐ์ฒด ์ž…๋‹ˆ๋‹ค.

CGSize

CGFloat ํƒ€์ž…์˜ ๋†’์ด, ๋„ˆ๋น„๊ฐ€ ๋“ค์–ด์žˆ๋Š” ๊ตฌ์กฐ์ฒด ์ž…๋‹ˆ๋‹ค.

CGRect

CGPoint์™€ CGSize๋ฅผ ๊ฒฐํ•ฉํ•œ ๊ตฌ์กฐ์ฒด ์ž…๋‹ˆ๋‹ค. CGRect๋Š” ์ง์‚ฌ๊ฐํ˜•์„ ๋œปํ•ฉ๋‹ˆ๋‹ค.

๋งŽ์€ ์ด๋‹ˆ์…œ๋ผ์ด์ €์™€ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

struct CGRect {
  var origin: CGPoint
  var size: CGSize
}

// example
var minY: CGFloat						// ์™ผ์ชฝ ์œ„ ๋ชจ์„œ๋ฆฌ
var midY: CGFloat 					// ์ˆ˜์ง ์ค‘๊ฐ„ ๊ฐ’
intersects(CGRect) -> Bool 	// ๋‹ค๋ฅธ ์ง์‚ฌ๊ฐํ˜•๊ณผ ๊ฒน์น˜๋Š”์ง€ ํ™•์ธ
intersect(CGRect)						// ๋‘ ์ง์‚ฌ๊ฐํ˜•์ด ๊ฒน์น˜๋Š” ๋ถ€๋ถ„์„ ๋ฆฌํ„ด
contains(CGPoint) -> Bool		// ํ•ด๋‹น ์ ์ด ํฌํ•จ๋˜๋Š”์ง€ ํ™•์ธ

View Coordiante System

origin

๋ทฐ๊ฐ€ ๊ทธ๋ ค์งˆ 2์ฐจ์› ์ขŒํ‘œ๊ณ„์ž…๋‹ˆ๋‹ค. iOS ์—์„œ ์ขŒํ‘œ๊ณ„๋Š” ์™ผ์ชฝ ์œ„ (0, 0) ๋ฅผ ์‹œ์ž‘์ ์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

points ๋‹จ์œ„, not pixels

์ด ์ขŒํ‘œ๊ณ„์˜ ๋‹จ์œ„๋Š” ํฌ์ธํŠธ points ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ํ”ฝ์…€ pixels ๊ณผ๋Š” ๋‹ค๋ฅธ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.

ํ•œ ํฌ์ธํŠธ ๋‹น ํ”ฝ์…€์ด ์–ผ๋งˆ๋‚˜ ๋งŽ๋ƒ์— ๋”ฐ๋ผ ํ•ด์ƒ๋„๊ฐ€ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.

ํ”ฝ์…€์€ ์Šคํฌ๋ฆฐ์„ ๊ตฌ์„ฑํ•˜๊ณ  ์žˆ๋Š” ์ž‘์€ ์ ์œผ๋กœ ๋ ˆํ‹ฐ๋‚˜ ๋””์Šคํ”Œ๋ ˆ์ด ๊ฐ™์€ ํ™”๋ฉด์—๋Š” ํ”ฝ์…€์ด ๋งŽ์•„ ํ•ด์ƒ๋„๊ฐ€ ๋†’์Šต๋‹ˆ๋‹ค. ํ”ฝ์…€์ด ๋งŽ์œผ๋ฉด ์ข‹์€ ์ด์œ ๋Š” ํฌ์ธํŠธ์˜ ๊ฒฝ๊ณ„๋ฅผ ๊ทธ๋ฆด ๋•Œ ๋” ์„ธ์„ธํ•˜๊ฒŒ ๊ทธ๋ฆด ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. 27ํฌ์ธํŠธ์—์„œ 28ํฌ์ธํŠธ๋กœ ์˜ฎ๊ฒจ๊ฐ„๋‹ค๊ณ  ํ• ๋•Œ, ์ € ํ•ด์ƒ๋„์—์„œ ํ”ฝ์…€์„ ํ•˜๋‚˜์”ฉ ์ฐ๋Š”๋‹ค๊ณ  ํ•œ๋‹ค๋ฉด ๊ณ ํ•ด์ƒ๋„์—์„œ๋Š” 27.2, 27.5 ๋“ฑ ๋” ์„ธ์„ธํ•˜๊ฒŒ ๊ทธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

bounds

๋ทฐ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” CGRect ๋ณ€์ˆ˜ ์ž…๋‹ˆ๋‹ค. ๋ทฐ๋Š” ๊ฐ๊ฐ ์ž์‹ ์˜ ์ขŒํ‘œ๊ณ„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. bounds ๋Š” ์ž๊ธฐ ์ž์‹ ์— ๋Œ€ํ•œ ์ขŒํ‘œ๊ณ„ ์ •๋ณด์ž…๋‹ˆ๋‹ค. ์ฆ‰, ๊ธฐ๋ณธ์ ์œผ๋กœ bounds์˜ origin์€ ํ•ญ์ƒ (0, 0)์ด ๋˜๊ณ  ์ž์‹ ์˜ ๋„ˆ๋น„์™€ ๋†’์ด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ทฐ๋ฅผ ๊ทธ๋ฆด ๋•Œ๋Š” bounds๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ด์™€๋Š” ๋‹ค๋ฅด๊ฒŒ frame ๋ณ€์ˆ˜๋„ ์žˆ๋Š”๋ฐ, frame์€ ๋“œ๋กœ์ž‰๊ณผ๋Š” ์ „ํ˜€ ๊ด€๊ณ„๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. frame๋„ CGRect ํƒ€์ž…์ด์ง€๋งŒ ์Šˆํผ ๋ทฐ์—์„œ ์ž์‹ ์ด ์–ด๋”” ์žˆ๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. frame์€ ์ž์‹ ์˜ ์ขŒํ‘œ๊ณ„๊ฐ€ ์•„๋‹ˆ๋ผ ์Šˆํผ ๋ทฐ์˜ ์ขŒํ‘œ๊ณ„๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค.

๋˜ ๋น„์Šทํ•˜๊ฒŒ center ๋˜ํ•œ ์ง€๊ธˆ ๋“œ๋กœ์ž‰ํ•˜๋Š” ์˜์—ญ์˜ ์ค‘์‹ฌ์ด ์•„๋‹ˆ๋ผ ์Šˆํผ ๋ทฐ์˜ ์ž…์žฅ์—์„œ ๋ณธ ๋ทฐ์˜ ์ค‘์‹ฌ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰ frame๊ณผ center๋Š” ์ง€๊ธˆ ์–ด๋””์„œ ๊ทธ๋ฆฌ๊ณ  ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋‚ด๊ณ , bounds๋Š” ์ง€๊ธˆ ๊ทธ๋ฆฌ๋Š” ๊ณณ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

frame๊ณผ bounds์˜ ๋†’์ด์™€ ๋„ˆ๋น„๊ฐ€ ๊ฐ™๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๊ฐ™์„ ํ•„์š”๊ฐ€ ์—†๊ณ  ํ•ญ์ƒ ๊ฐ™์ง€๋„ ์•Š์Šต๋‹ˆ๋‹ค.

๋ทฐ๋ฅผ ํšŒ์ „ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ทฐ ์ž์ฒด์˜ ๋†’์ด์™€ ๋„ˆ๋น„๋Š” ๋ณ€ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— bounds๋Š” ๊ทธ๋Œ€๋กœ๊ฒ ์ง€๋งŒ, ํšŒ์ „ํ•˜๋Š” ์˜์—ญ์„ ๋ชจ๋‘ ๊ฐ์‹ธ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— frame์€ ๋” ์ปค์ง‘๋‹ˆ๋‹ค.

Creating Views

๋ทฐ์˜ ์ƒ์„ฑ์€ ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋”์™€ ์ฝ”๋“œ๋กœ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋“œ์—์„œ๋Š” ๋ทฐ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋Œ์–ด๋‹ค ๋†“์œผ๋ฉด ๋˜๊ณ 

์ฝ”๋“œ๋กœ๋Š” ํ•ด๋‹น ๋ทฐ์˜ ํ”„๋ ˆ์ž„์„ ์ค˜์„œ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํ”„๋ ˆ์ž„์„ ๋”ฐ๋กœ ์ง€์ •ํ•ด์ฃผ์ง€ ์•Š๋Š”๋‹ค๋ฉด ๋ทฐ์˜ ์ขŒ์ƒ๋‹จ ๋ชจ์„œ๋ฆฌ์ธ (0,0)์— ๋งž์ถฐ์ง‘๋‹ˆ๋‹ค.

addSubview๋ฅผ ํ†ตํ•ด ๋ทฐ๋ฅผ ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค.

let myView = UIView(frame: otherView) // otherView์˜ ํ”„๋ ˆ์ž„๊ณผ ๋™์ผํ•œ ๋ทฐ ์ƒ์„ฑ
let defaultView = UIView()	// origin (0,0)์— ๋ทฐ ์ƒ์„ฑ

view.addSubview(myView)

Custom Views

iOS์—์„œ ์ง์ ‘ ๋ทฐ๋ฅผ ๊ทธ๋ฆด ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ ํ•œ ๊ฐ€์ง€๋ฐ–์— ์—†์Šต๋‹ˆ๋‹ค.

override func draw(_ rect: CGRect)

UIView์˜ draw ๋ฉ”์†Œ๋“œ๋กœ ๋ทฐ์˜ ๊ฒฝ๊ณ„๋ฅผ ๊ทธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹จ, ์ด draw ํ•จ์ˆ˜๋Š” ์ ˆ๋Œ€ ์ง์ ‘ ํ˜ธ์ถœํ•ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ ๋ทฐ๋ฅผ ๋‹ค์‹œ ๊ทธ๋ฆฌ๊ณ  ์‹ถ๋‹ค๋ฉด, ๋‹ค์Œ ๋‘ ๋ฉ”์†Œ๋“œ ์ค‘ ํ•˜๋‚˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. draw ํ•จ์ˆ˜๋Š” ์˜ค์ง iOS ์‹œ์Šคํ…œ๋งŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

setNeedsDisplay(_ rect: CGRect) ๋ฉ”์†Œ๋“œ์—์„œ rect๋Š” ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ทฐ ์ „์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ํŠน์ • ๋ทฐ๋งŒ ๋‹ค์‹œ ๊ทธ๋ ค๋„ ๋œ๋‹ค๋ฉด ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š”๊ฒŒ ํšจ์œจ์ ์ด๊ฒ ์ฃ . ๊ทธ๋Ÿฌ๋‚˜ ๋„ˆ๋ฌด ๋งŽ์€ ์ž์›์„ ์“ฐ๊ฑฐ๋‚˜ 3D ๊ทธ๋ž˜ํ”ฝ์ด ์•„๋‹ˆ๋ผ ์‰ฝ๊ฒŒ ๊ทธ๋ฆด ์ˆ˜ ์žˆ๋Š” ๋ทฐ๋ผ๋ฉด rect๋Š” ๋ฌด์‹œํ•ด๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

setNeedsDisplay()
setNeedsDisplay(_ rect: CGRect) // ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ๋‹ค์‹œ ๊ทธ๋ฆฐ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ด์ œ ์ง„์งœ ๋ทฐ๋ฅผ ๊ทธ๋ฆฌ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ฝ”์–ด ๊ทธ๋ž˜ํ”ฝ์Šค๋ฅผ ์ด์šฉํ•˜๊ฑฐ๋‚˜ ๊ฐ์ฒด์ง€ํ–ฅ์ ์œผ๋กœ UIBezierPath ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋จผ์ € ์ฝ”์–ด ๊ทธ๋ž˜ํ”ฝ์Šค์—์„œ ๋“œ๋กœ์ž‰ํ•˜๋Š” ๊ฒƒ์˜ ํ•ต์‹ฌ ๊ฐœ๋…๋ถ€ํ„ฐ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Core Graphics Concepts

  1. Contexts ๊ฐ€์ ธ์˜ค๊ธฐ

์ฝ”์–ด ๊ทธ๋ž˜ํ”ฝ์Šค๋Š” ์ปจํ…์ŠคํŠธ contexts๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. UIBezierPath๋Š” ์ž๋™์œผ๋กœ ์ปจํ…์ŠคํŠธ๋ฅผ ์–ป์–ด์˜ค์ง€๋งŒ, UIBezierPath๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ปจํ…์ŠคํŠธ๋ฅผ ์–ป์–ด์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Swift์˜ ์ „์—ญ๋ณ€์ˆ˜์ธ UIGraphicsGetCurrentContext() ๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋“œ๋กœ์ž‰ ํ•  ์ปจํ…์ŠคํŠธ๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ถœ๋ ฅ์„ ํ•˜๊ฑฐ๋‚˜ ํ™”๋ฉด์—์„œ ๋“œ๋กœ์ž‰์„ ๊ป๋‹ค ์ผฐ๋‹ค ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ์ปจํ…์ŠคํŠธ๋„ ์žˆ์„ ์ˆ˜ ์žˆ๋Š”๋ฐ, draw(_ rect: CGRect) ์—์„œ๋Š” UIGraphicsGetCurrentContext() ๋งŒ์œผ๋กœ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

  1. Path ์ƒ์„ฑ (out of lines or arcs, etc)
  2. attributes ์„ค์ • (colors, fonts, textures lineWidths, lineCaps, etc)
  3. ์œ„์— ์„ค์ •ํ•œ path์™€ attributes์— ๋”ฐ๋ผ ์„ ์„ ๊ทธ๋ฆฌ๊ฑฐ๋‚˜ ์ฑ„์›๋‹ˆ๋‹ค. (stroke or fill)

UIBezierPath

์œ„์—์„œ ์ง์ ‘ ์ž‘์—…ํ•ด์ฃผ๋Š” path, attributes, stroke ๋“ฑ๋“ฑ์˜ ์ž‘์—…๋“ค์ด ๋‹ด๊ฒจ์žˆ๋Š” ๊ฐ€๋ฐฉ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์ข‹์Šต๋‹ˆ๋‹ค.

Defining a Path

์ด์ œ ๊ตฌ์ฒด์ ์œผ๋กœ ๊ทธ๋ ค๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

UIBezierPath๋ฅผ ์‚ฌ์šฉํ•ด ์‚ผ๊ฐํ˜•์„ ๊ทธ๋ฆฐ๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// UIBezierPath ์ƒ์„ฑ
let path = UIBezierPath()

// ๊ฒฝ๋กœ ๊ทธ๋ฆฌ๊ธฐ
path.move(to: CGPoint(80, 50))
path.addLine(to: CGPoint(140, 150))
path.addLine(to: CGPoint(10, 150))

// ํ•„์š”ํ•˜๋‹ค๋ฉด close๋ฅผ ์‹œ์ž‘ ์œ„์น˜๋กœ ๋งˆ๋ฌด๋ฆฌ
path.close

ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ™”๋ฉด์—๋Š” ์•„๋ฌด๋Ÿฐ ๋ณ€ํ™”๋„ ์ผ์–ด๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฑด ๋‹จ์ˆœํžˆ ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ–ˆ์„ ๋ฟ, ํ™”๋ฉด์— ๊ทธ๋ฆฌ๋ ค๋ฉด attributes ์™€ stroke, fill ๋“ฑ์„ ์„ค์ •ํ•ด ์–ด๋–ป๊ฒŒ ๊ทธ๋ฆด์ง€ ์•Œ๋ ค์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

UIColor.green.setFill()
UIColor.red.setStroke()
path.lineWidth = 3.0
path.fill()
path.stroke()

์ด๋ฐ–์—๋„ clip ๋“ฑ ๋‹ค์–‘ํ•œ ์ผ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Fonts

preferred font

preferred font` ๋ฅผ ์ƒํ™ฉ์— ๋งž์ถฐ ์ž˜ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. preferred font๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž์˜ ์„ค์ •์— ๊ธ€์ž์˜ ํฌ๊ธฐ๋ฅผ ๊ฐ€๋ณ€์ ์œผ๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Interface Builder์—์„œ ์‰ฝ๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๊ณ  ์ฝ”๋“œ๋กœ๋„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ๋กœ๋Š” UIFont์˜ static ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

static func preferredFont(forTextStlye: UIFonteTextStyle) -> UIFont

UIFontTextStyle
	.headline
	.body
	.footnode
	...

custom font

Custom Font ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

let font = UIFont(name: "Helvetica", size: 36.0)

ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด size๊ฐ€ 36์œผ๋กœ ๊ณ ์ •๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๋ณ€์ ์œผ๋กœ ๋ณ€ํ•  ์ˆ˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿด๋•Œ metrics ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

let metrics = UIFontMetrics(forTextStyle: .body)
let fontToUse = metrics.scaledFont(for: font)

system font

์ฃผ๋กœ ๋ฒ„ํŠผ ์ œ๋ชฉ ๊ฐ™์€ ๊ณณ์—๋งŒ ์‚ฌ์šฉ๋˜๋Š” ํฐํŠธ์ž…๋‹ˆ๋‹ค.

static func systemFont(ofSize: CGSize) -> UIFont
static func boldSystemFont(ofSize: CGSize) -> UIFont

Drawing Images

UIImageView ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์ด๋ฏธ์ง€๋Š” UIImage ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์„œ ์‚ฌ์šฉํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Image๋ฅผ ์–ป์–ด์˜ค๋Š” ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

Asset.xcasset ์— ์žˆ๋Š” ์ด๋ฏธ์ง€ ๊ฐ€์ ธ์˜ค๊ธฐ

let image: UIImage? = UIImage(name: "foo")

filesystem์— ์žˆ๋Š” ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ์ธํ„ฐ๋„ท์—์„œ bit ๊ฐ€๋ฐฉ์ธ Data ํƒ€์ž…์„ ๋ฐ›์•„์™€ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

let image: UIImage? = UIImage(contentsOfFile: pathString)
let image: UIImage? = UIImage(data: aData)

UIGraphicsBeginImageContext(CGSize) ๋ฅผ ์‚ฌ์šฉํ•ด Core Graphics๋กœ ์ง์ ‘ ๊ทธ๋Ÿด ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

UIImage๋ฅผ ์–ป์–ด์™”๋‹ค๋ฉด ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ๊ทธ๋ ค๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

let image: UIImage = ...
image.draw(at point: aCGPoint)  // image๋ฅผ ์™ผ์ชฝ ์ƒ๋‹จ ๋ชจ์„œ๋ฆฌ์— ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.
image.draw(in rect: aCGRect) // rect์— ๋งž์ถฐ ์ด๋ฏธ์ง€๋ฅผ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.
image.drawAsPattern(in rect: aCGRect) // rect์— ๋งž์ถฐ ์ด๋ฏธ์ง€๋ฅผ ํƒ€์ผ์ฒ˜๋Ÿผ ๋ฐ˜๋ณต์ ์œผ๋กœ ๊ทธ๋ ค๋ƒ…๋‹ˆ๋‹ค.

bounds๊ฐ€ ๋ณ€ํ–ˆ์„ ๋•Œ ๋‹ค์‹œ ๊ทธ๋ฆฌ๊ธฐ

๋Œ€ํ‘œ์ ์œผ๋กœ ๊ธฐ๊ธฐ๋ฅผ ํšŒ์ „์‹œ์ผฐ์„ ๋•Œ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์‹œ ๊ทธ๋ ค์ค„ ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ iOS์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” ๋‹ค์‹œ ๊ทธ๋ ค์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๋Ÿด ๋•Œ UIView์˜ content mode ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. view๊ฐ€ ์–ด๋–ค ์ข…๋ฅ˜์˜ content๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

var contentMode: UIViewContentMode

UIViewContentMode

3๊ฐ€์ง€ ์ข…๋ฅ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๋น„ํŠธ ์œ ์ง€ ์ƒˆ๋กœ ๊ทธ๋ฆฌ์ง€ ์•Š๊ณ  ํฌ๊ธฐ๋„ ์กฐ์ ˆํ•˜์ง€ ์•Š๊ณ  ๋น„ํŠธ๋งŒ ์›€์ง์ž…๋‹ˆ๋‹ค. ๊ฑฐ์˜ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. .left/.right/.top/.bottom/.topRight/...
  2. ๋น„ํŠธ ๋Š˜์ด๊ธฐ ๋น„ํŠธ๋ฅผ ๋Š˜์ด๊ฑฐ๋‚˜ ์ค„์—ฌ์„œ ์ƒˆ๋กœ์šด ๊ณต๊ฐ„์— ๋งž์ถฅ๋‹ˆ๋‹ค. ํ™”๋ฉด์˜ ๋น„์œจ์„ ์ž˜ ๊ณ ๋ คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. .sacleToFill / .scaleAspectFill / .scaleAspectFit // scaleToFil ์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๊ฐ–์Šต๋‹ˆ๋‹ค.
  3. ๋‹ค์‹œ ๊ทธ๋ฆฌ๊ธฐ (redraw) ๊ฒฝ๊ณ„๊ฐ€ ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ draw(rect)๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์ƒˆ๋กœ ๋“œ๋กœ์ž‰ํ•ฉ๋‹ˆ๋‹ค. draw(rect)๋ฅผ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ ๊ฒฝ๊ณ„์˜ ์œ„์น˜๋ฅผ ์•Œ์•„์„œ ๊ฒฝ๊ณ„์— ๋งž๊ฒŒ ๋“œ๋กœ์ž‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

bounds๊ฐ€ ๋ณ€ํ•  ๋•Œ

bounds๊ฐ€ ๋ณ€ํ™”ํ•˜๋ฉด subviews๋ฅผ ์žฌ๋ฐฐ์น˜ํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

subview๋“ค์— Autolayout ์„ ์„ค์ •ํ•ด๋‘์ง€ ์•Š์•˜๋‹ค๋ฉด, layoutSubviews() ๋ฅผ ์‚ฌ์šฉํ•ด ์ˆ˜๋™์œผ๋กœ ๋ ˆ์ด์•„์›ƒ์„ ์žฌ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, layoutSubviews() ๋Š” subview์— autolayout์ด ์ ์šฉ๋˜์–ด ์žˆ์ง€ ์•Š์„ ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

override func layoutSubviews() {
  super.layoutSubviews()
}

CustomStringConvertible

์ด ํ”„๋กœํ† ์ฝœ์„ ์ƒ์†๋ฐ›์œผ๋ฉด var description: String ์„ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด์„œ ๊ฐ์ฒด์˜ description์„ ๋งŒ๋“ค์–ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

struct PlayingCard: CustomStringConvertible {
    
    var description: String { return "\(suit)\(rank)" }
    
    var suit: Suit
    var rank: Rank
  	...
}