Slide 1

Slide 1 text

如何⽀支援 Mac OS X 的⾼高解析度模式 楊維中 a.k.a zonble [email protected] Sunday, August 26,

Slide 2

Slide 2 text

萬惡的根源 Sunday, August 26,

Slide 3

Slide 3 text

開發環境 • MacBook Pro 2012 • 沒有新機器怎麼辦? • 使⽤用模擬環境 Sunday, August 26,

Slide 4

Slide 4 text

模擬環境 Sunday, August 26,

Slide 5

Slide 5 text

模擬環境 Sunday, August 26,

Slide 6

Slide 6 text

模擬環境 Quartz Debug Sunday, August 26,

Slide 7

Slide 7 text

模擬環境 Sunday, August 26,

Slide 8

Slide 8 text

模擬環境 Sunday, August 26,

Slide 9

Slide 9 text

Sunday, August 26,

Slide 10

Slide 10 text

如何⽀支援? • 使⽤用兩倍圖檔 • 改⽤用向量圖形 Sunday, August 26,

Slide 11

Slide 11 text

使⽤用兩倍圖檔 • 跟 iOS ⼀一樣 • 所有⽤用到的圖⽚片 的檔名加上 @2x,然後加到 應⽤用程式中 Sunday, August 26,

Slide 12

Slide 12 text

使⽤用向量圖 • 向量圖檔格式很 多:Adobe Illustrator、 Corel Draw、 SVG… • Mac OS X 系統 ⽀支援的向量格 式,簡單,就是 PDF Sunday, August 26,

Slide 13

Slide 13 text

Core Animation • CALayer 必須要⼿手動調整屬性,才有辦 法⽀支援 Retina Display • contents 直接給 @2x 圖⽚片是沒⽤用的 • 必須⼿手動設定 contentScale Sunday, August 26,

Slide 14

Slide 14 text

iOS 上⾯面 • aLayer. contentsScale = [UISCreen mainScreen].scale • 反正⼀一般來說,我們的 UI 只會出現在 mainScreen 上。雖然可以外接投影機, 使⽤用另外⼀一個 UIScreen,但是⼀一般不會 有⼈人去寫這種 App Sunday, August 26,

Slide 15

Slide 15 text

Mac OS X • CALayer 不⼀一定會出現在哪個 Screen 裡頭, ⽽而是要由⺫⽬目前 layer 所在的 Window 決定是否 要使⽤用⾼高解析度 • 詢問 NSWindow 的 -backingScaleFactor • Window 還可以在不同 Screen (主螢幕、延 伸螢幕)之間移動 • contentsScale 需要隨時改變 • 還有…向下相容,你應該不會只⽀支援 10.7.4 以上的系統 Sunday, August 26,

Slide 16

Slide 16 text

改變解析度的時機 • Layer 被放到某個 Window 的時候 • 因為 Window 移動⽽而造成 Window 的 scale 改變的時候(Notification) • 以下範例是假設 rootLayer 這個物件被擺 在某個 NSView 裡頭 Sunday, August 26,

Slide 17

Slide 17 text

Layer 被放到某個 Window 的時候 - (void)viewDidMoveToWindow { if ([rootLayer respondsToSelector:@selector(contentsScale)]) { // 舊版的 OS 的 CALayer 不⼀一定會有 contentsScale // 舊版的 OS 的 Window 也不⼀一定會有 backingScaleFactor… CGFloat scale = [(id)[self window] backingScaleFactor]; [(id)rootLayer setContentsScale:scale]; } } Sunday, August 26,

Slide 18

Slide 18 text

訂閱 Window 移動⽽而 解析度改變的通知 • 訂閱 NSWindowDidChangeBackingPropertiesN otification • 但因為舊版系統沒有,所以直接訂閱字 串 @” NSWindowDidChangeBackingPropertiesN otification” Sunday, August 26,

Slide 19

Slide 19 text

訂閱 Window 移動⽽而 解析度改變的通知 • 在 viewDidMoveToWindow 訂閱 • 在 removeFromSuperview 取消 • 我們先來把剛剛那段修改 contentsScale 的程式拆出來 Sunday, August 26,

Slide 20

Slide 20 text

拆出來的 private method - (void)_updateContentScale { if (![self window]) { return; } if ([rootLayer respondsToSelector:@selector(contentsScale)]) { CGFloat scale = [(id)[self window] backingScaleFactor]; [(id)rootLayer setContentsScale:scale]; } } Sunday, August 26,

Slide 21

Slide 21 text

訂閱通知 - (void)viewDidMoveToWindow { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(scale DidChange:) name:@"NSWindowDidChangeBackingPropertiesNotification" object:[self window]]; [self _updateContentScale]; } - (void)removeFromSuperview { [super removeFromSuperview]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)scaleDidChange:(NSNotification *)n { [self _updateContentScale]; } Sunday, August 26,

Slide 22

Slide 22 text

向下相容 • ⽤用舊版的 SDK 編譯,compiler 會跟你抱 怨沒有 contentsScale 與 backingScaleFactor… 很討厭 Sunday, August 26,

Slide 23

Slide 23 text

為了向下相容弄出來 的⻤⿁鬼 Category… @interface NSObject (RetinaDisplay) - (void)setContentsScale:(CGFloat)inScale; - (CGFloat)backingScaleFactor; @end Sunday, August 26,

Slide 24

Slide 24 text

That’a all! Sunday, August 26,