Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Retina Mac

Retina Mac

Weizhong Yang

August 26, 2012
Tweet

More Decks by Weizhong Yang

Other Decks in Technology

Transcript

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

    View full-size slide

  2. 萬惡的根源
    Sunday, August 26,

    View full-size slide

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

    View full-size slide

  4. 模擬環境
    Sunday, August 26,

    View full-size slide

  5. 模擬環境
    Sunday, August 26,

    View full-size slide

  6. 模擬環境
    Quartz Debug
    Sunday, August 26,

    View full-size slide

  7. 模擬環境
    Sunday, August 26,

    View full-size slide

  8. 模擬環境
    Sunday, August 26,

    View full-size slide

  9. Sunday, August 26,

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  17. 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,

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  20. 拆出來的 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,

    View full-size slide

  21. 訂閱通知
    - (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,

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  24. That’a all!
    Sunday, August 26,

    View full-size slide