-
-
Save leoschweizer/667bf1476e25333459a2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "CKSwitchComponent.h" | |
#import <ComponentKit/CKComponentSubclass.h> | |
#import <ComponentKit/CKComponentScope.h> | |
#import <ComponentKit/CKComponentController.h> | |
#import "CKComponentInternal.h" | |
void runOnMainQueueWithoutDeadlocking(void (^block)(void)) { | |
if ([NSThread isMainThread]) { | |
block(); | |
} else { | |
dispatch_sync(dispatch_get_main_queue(), block); | |
} | |
} | |
@interface CKSwitchComponentController : CKComponentController | |
@property (nonatomic, readwrite) UISwitch *switchView; | |
@end | |
@interface CKSwitchComponent () | |
@property (nonatomic) BOOL isOnState; | |
@property (nonatomic) CKViewComponentAttributeValueMap viewAttributes; | |
@property (nonatomic) CKComponentAction userAction; | |
@end | |
@implementation CKSwitchComponentController | |
- (instancetype)init { | |
if (self = [super init]) { | |
runOnMainQueueWithoutDeadlocking(^{ | |
self->_switchView = [[UISwitch alloc] init]; | |
}); | |
} | |
return self; | |
} | |
- (void)componentDidAcquireView { | |
[super componentDidAcquireView]; | |
[self.view.subviews enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) { | |
[subview removeFromSuperview]; | |
}]; | |
[self.switchView addTarget:self action:@selector(onSwitchValueChanged:) forControlEvents:UIControlEventValueChanged]; | |
[self.view addSubview:self.switchView]; | |
} | |
- (void)didUpdateComponent { | |
[super didUpdateComponent]; | |
CKSwitchComponent *switchComponent = (id)self.component; | |
CK::Component::AttributeApplicator::apply(self.switchView, {[UISwitch class], switchComponent.viewAttributes}); | |
// Note: the isOn state can't be handled through the viewAttributes, since cancelling | |
// a switch action would then be a no-op (old and new viewAttributes are equal and thus | |
// not applied to the view; this is a force-apply so to speak) | |
[self.switchView setOn:switchComponent.isOnState]; | |
} | |
- (void)onSwitchValueChanged:(id)sender { | |
CKSwitchComponent *switchComponent = (id)self.component; | |
CKComponentActionSend(switchComponent.userAction, self.component); | |
} | |
@end | |
@implementation CKSwitchComponent | |
+ (CKComponentSize)fixedSize { | |
static CKComponentSize size; | |
static dispatch_once_t onceToken; | |
dispatch_once(&onceToken, ^{ | |
UISwitch *prototype = [[UISwitch alloc] init]; | |
size = { | |
.width = prototype.frame.size.width, | |
.height = prototype.frame.size.height | |
}; | |
}); | |
return size; | |
} | |
+ (instancetype)newWithIsOn:(BOOL)isOn | |
viewAttributes:(const CKViewComponentAttributeValueMap &)viewAttributes | |
action:(CKComponentAction)action | |
{ | |
CKComponentScope scope(self); | |
CKViewComponentAttributeValueMap attributes(viewAttributes); | |
CKSwitchComponent *c = [super newWithView:{ | |
[UIView class] | |
} | |
size:[self fixedSize]]; | |
c.isOnState = isOn; | |
c.viewAttributes = attributes; | |
c.userAction = action; | |
return c; | |
} | |
- (BOOL)isOn { | |
CKSwitchComponentController *controller = (id)self.controller; | |
return controller.switchView.isOn; | |
} | |
- (void)reset { | |
CKSwitchComponentController *controller = (id)self.controller; | |
runOnMainQueueWithoutDeadlocking(^{ | |
controller.switchView.on = !controller.switchView.isOn; | |
}); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment