Skip to content

Instantly share code, notes, and snippets.

@jwilling
Last active February 6, 2018 12:44

Revisions

  1. jwilling renamed this gist Dec 28, 2013. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. jwilling revised this gist Dec 28, 2013. 2 changed files with 21 additions and 21 deletions.
    40 changes: 20 additions & 20 deletions IBNView.m
    Original file line number Diff line number Diff line change
    @@ -1,44 +1,44 @@
    #import "IBNView.h"
    #import "LBHView.h"
    #import "JRSwizzle.h"
    #import <objc/runtime.h>

    @interface CALayer (IBNBackingLayerHacks)
    @interface CALayer (LBHBackingLayerHacks)

    @property (nonatomic, assign) BOOL ibn_ignoreNSViewBackingLayerSynchronization;
    @property (nonatomic, assign) BOOL lbh_ignoreNSViewBackingLayerSynchronization;

    @end

    static void *IBNBackingLayerSynchronizationAssociatedObjectKey = &IBNBackingLayerSynchronizationAssociatedObjectKey;
    static void *LBHBackingLayerSynchronizationAssociatedObjectKey = &LBHBackingLayerSynchronizationAssociatedObjectKey;

    @implementation CALayer (IBNBackingLayerHacks)
    @implementation CALayer (LBHBackingLayerHacks)

    - (void)setIbn_ignoreNSViewBackingLayerSynchronization:(BOOL)ignores {
    objc_setAssociatedObject(self, IBNBackingLayerSynchronizationAssociatedObjectKey, @(ignores), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    - (void)setLbh_ignoreNSViewBackingLayerSynchronization:(BOOL)ignores {
    objc_setAssociatedObject(self, LBHBackingLayerSynchronizationAssociatedObjectKey, @(ignores), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }

    - (BOOL)ibn_ignoreNSViewBackingLayerSynchronization {
    return [objc_getAssociatedObject(self, IBNBackingLayerSynchronizationAssociatedObjectKey) boolValue];
    - (BOOL)lbh_ignoreNSViewBackingLayerSynchronization {
    return [objc_getAssociatedObject(self, LBHBackingLayerSynchronizationAssociatedObjectKey) boolValue];
    }

    - (void)ibn_setAffineTransform:(CGAffineTransform)m {
    if (self.ibn_ignoreNSViewBackingLayerSynchronization) {
    - (void)lbh_setAffineTransform:(CGAffineTransform)m {
    if (self.lbh_ignoreNSViewBackingLayerSynchronization) {
    // do nothing
    } else {
    [self ibn_setAffineTransform:m];
    [self lbh_setAffineTransform:m];
    }
    }

    - (void)ibn_setAnchorPoint:(CGPoint)anchorPoint {
    if (self.ibn_ignoreNSViewBackingLayerSynchronization) {
    - (void)lbh_setAnchorPoint:(CGPoint)anchorPoint {
    if (self.lbh_ignoreNSViewBackingLayerSynchronization) {
    // do nothing
    } else {
    [self ibn_setAnchorPoint:anchorPoint];
    [self lbh_setAnchorPoint:anchorPoint];
    }
    }

    @end

    @implementation IBNView
    @implementation LBHView

    - (instancetype)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    @@ -60,19 +60,19 @@ - (CALayer *)makeBackingLayer {
    NSError *error = nil;

    // Swizzle the setters for anchor point and affine transform.
    [nsBackingLayerClass jr_swizzleMethod:@selector(setAnchorPoint:) withMethod:@selector(ibn_setAnchorPoint:) error:&error];
    [nsBackingLayerClass jr_swizzleMethod:@selector(setAffineTransform:) withMethod:@selector(ibn_setAffineTransform:) error:&error];
    [nsBackingLayerClass jr_swizzleMethod:@selector(setAnchorPoint:) withMethod:@selector(lbh_setAnchorPoint:) error:&error];
    [nsBackingLayerClass jr_swizzleMethod:@selector(setAffineTransform:) withMethod:@selector(lbh_setAffineTransform:) error:&error];

    if (error != nil) {
    IBNLog(@"Fatal error: could not swizzle the view's backing layer! %@", error);
    NSLog(@"Fatal error: could not swizzle the view's backing layer! %@", error);
    }
    });

    return backingLayer;
    }

    - (void)setIgnoreNSViewBackingLayerSynchronization:(BOOL)ignoreSynchronization {
    self.layer.ibn_ignoreNSViewBackingLayerSynchronization = ignoreSynchronization;
    self.layer.lbh_ignoreNSViewBackingLayerSynchronization = ignoreSynchronization;
    }

    @end
    2 changes: 1 addition & 1 deletion IBNView.h → LBHView.h
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    #import <Cocoa/Cocoa.h>

    @interface IBNView : NSView
    @interface LBHView : NSView

    /// This property controls whether the view can indirectly control its
    /// backing layer's properties, specifically the following:
  3. jwilling created this gist Dec 28, 2013.
    17 changes: 17 additions & 0 deletions IBNView.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,17 @@
    #import <Cocoa/Cocoa.h>

    @interface IBNView : NSView

    /// This property controls whether the view can indirectly control its
    /// backing layer's properties, specifically the following:
    /// `affineTransform`
    /// `anchorPoint`
    ///
    /// These properties cannot be modified on the layer during the time that
    /// this property is enabled.
    ///
    /// This is useful for preventing NSView from resetting custom modifications
    /// to the layer, such as transforms for custom animations.
    @property (nonatomic, assign) BOOL ignoreNSViewBackingLayerSynchronization;

    @end
    78 changes: 78 additions & 0 deletions IBNView.m
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,78 @@
    #import "IBNView.h"
    #import "JRSwizzle.h"
    #import <objc/runtime.h>

    @interface CALayer (IBNBackingLayerHacks)

    @property (nonatomic, assign) BOOL ibn_ignoreNSViewBackingLayerSynchronization;

    @end

    static void *IBNBackingLayerSynchronizationAssociatedObjectKey = &IBNBackingLayerSynchronizationAssociatedObjectKey;

    @implementation CALayer (IBNBackingLayerHacks)

    - (void)setIbn_ignoreNSViewBackingLayerSynchronization:(BOOL)ignores {
    objc_setAssociatedObject(self, IBNBackingLayerSynchronizationAssociatedObjectKey, @(ignores), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }

    - (BOOL)ibn_ignoreNSViewBackingLayerSynchronization {
    return [objc_getAssociatedObject(self, IBNBackingLayerSynchronizationAssociatedObjectKey) boolValue];
    }

    - (void)ibn_setAffineTransform:(CGAffineTransform)m {
    if (self.ibn_ignoreNSViewBackingLayerSynchronization) {
    // do nothing
    } else {
    [self ibn_setAffineTransform:m];
    }
    }

    - (void)ibn_setAnchorPoint:(CGPoint)anchorPoint {
    if (self.ibn_ignoreNSViewBackingLayerSynchronization) {
    // do nothing
    } else {
    [self ibn_setAnchorPoint:anchorPoint];
    }
    }

    @end

    @implementation IBNView

    - (instancetype)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    if (self == nil) return nil;
    self.wantsLayer = YES;
    self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;

    return self;
    }

    - (CALayer *)makeBackingLayer {
    CALayer *backingLayer = [super makeBackingLayer];

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    // Get the class for _NSBackingLayer.
    Class nsBackingLayerClass = backingLayer.class;

    NSError *error = nil;

    // Swizzle the setters for anchor point and affine transform.
    [nsBackingLayerClass jr_swizzleMethod:@selector(setAnchorPoint:) withMethod:@selector(ibn_setAnchorPoint:) error:&error];
    [nsBackingLayerClass jr_swizzleMethod:@selector(setAffineTransform:) withMethod:@selector(ibn_setAffineTransform:) error:&error];

    if (error != nil) {
    IBNLog(@"Fatal error: could not swizzle the view's backing layer! %@", error);
    }
    });

    return backingLayer;
    }

    - (void)setIgnoreNSViewBackingLayerSynchronization:(BOOL)ignoreSynchronization {
    self.layer.ibn_ignoreNSViewBackingLayerSynchronization = ignoreSynchronization;
    }

    @end