SlideShare a Scribd company logo
1 of 44
Download to read offline
BloodMagic 
Custom property attributes 
CocoaHeads, 2014
WHOAMI 
Github: 
AlexDenisov 
IRC: AlexDenisov 
1101_debian 
Twitter:
Outline 
• What BloodMagic is 
• How to use it 
• How to extend it 
• How does it work 
• Q & A
What BloodMagic is
Problem 
@interface ViewController : UIViewController 
@property (nonatomic) NSMutableArray *resources; 
@property (nonatomic) ProgressView *progressView; 
@property (nonatomic) ErrorView *errorView; 
@property (nonatomic) DataLoader *dataLoader; 
@end
Lazy Initialization 
@implementation ViewController 
- (NSMutableArray *)resources 
{ 
if (!_resources) { 
_resources = [NSMutableArray new]; 
} 
return _resources; 
} 
- (ProgressView *)progressView 
{ 
if (!_progressView) { 
_progressView = [ProgressView new]; 
} 
return _progressView; 
} 
- (ErrorView *)errorView 
{ 
if (!_errorView) { 
_errorView = [ErrorView new]; 
} 
return _errorView; 
} 
- (DataLoader *)dataLoader 
{ 
if (!_dataLoader) { 
_dataLoader = [DataLoader new]; 
} 
return _dataLoader; 
} 
@end
- (PropertyClass *)propertyName 
{ 
if (!_propertyName) { 
_propertyName = [PropertyClass new]; 
} 
return _propertyName; 
} 
A lot of Boilerplate Code
Just add ‘lazy’ attribute 
@interface ViewController : UIViewController 
@property (nonatomic, lazy) NSMutableArray *resources; 
@property (nonatomic, lazy) CenterProgress *centerProgress; 
@property (nonatomic, lazy) BottomProgress *bottomProgress; 
@property (nonatomic, lazy) DataLoader *dataLoader; 
@end
Just add ‘lazy’ attribute 
@interface ViewController : UIViewController 
@property (nonatomic, lazy) NSMutableArray *resources; 
@property (nonatomic, lazy) CenterProgress *centerProgress; 
@property (nonatomic, lazy) BottomProgress *bottomProgress; 
@property (nonatomic, lazy) DataLoader *dataLoader; 
@end 
/tmp/lazy_test ➜ make 
… 
error: unknown property attribute 'lazy' 
@property (nonatomic, lazy) NSMutableArray *resources; 
^ 
…
BloodMagic 
a mechanism for creating 
custom property attributes 
based on your code
Let’s add magic 
#import <BloodMagic/Lazy.h> 
@interface ViewController : UIViewController 
<BMLazy> 
@property (nonatomic) NSMutableArray *resources; 
@property (nonatomic) ProgressView *progressView; 
@property (nonatomic) ErrorView *errorView; 
@property (nonatomic) DataLoader *dataLoader; 
@end
Let’s add magic 
@implementation ViewController 
@dynamic resources; 
@dynamic progressView; 
@dynamic errorView; 
@dynamic dataLoader; 
- (void)actOnSomething 
{ 
[self.dataLoader loadNextPage]; 
// ^ new object created 
} 
@end
Magic Happened 
@implementation ViewController 
@dynamic resources; 
@dynamic progressView; 
@dynamic errorView; 
@dynamic dataLoader; 
@end 
BloodMagic 
@implementation ViewController 
- (NSMutableArray *)resources 
{ 
if (!_resources) { 
_resources = [NSMutableArray new]; 
} 
return _resources; 
} 
- (ProgressView *)progressView 
{ 
if (!_progressView) { 
_progressView = [ProgressView new]; 
} 
return _progressView; 
} 
- (ErrorView *)errorView 
{ 
if (!_errorView) { 
_errorView = [ErrorView new]; 
} 
return _errorView; 
} 
- (DataLoader *)dataLoader 
{ 
if (!_dataLoader) { 
_dataLoader = [DataLoader new]; 
} 
return _dataLoader; 
} 
@end
How to use 
BloodMagic
Single Custom Attribute 
#import <BloodMagic/Lazy.h> 
@interface ViewController : UIViewController 
<BMLazy> 
@property (nonatomic, bm_lazy) DataLoader *dataLoader; 
@end
Single Custom Attribute 
#import "ViewController.h" 
@implementation ViewController 
@dynamic dataLoader; 
- (void)viewDidLoad 
{ 
[super viewDidLoad]; 
[self.dataLoader loadNextPage]; 
} 
@end
Single Custom Attribute 
#import "ViewController.h" 
@implementation ViewController 
@dynamic dataLoader; 
- (void)viewDidLoad 
{ 
[super viewDidLoad]; 
[self.dataLoader loadNextPage]; 
// ^ new object created 
} 
@end
Multiple Custom Attributes 
#import <BloodMagic/Lazy.h> 
#import <BloodMagic/Partial.h> 
@interface ViewController : UIViewController 
<BMLazy, 
BMPartial> 
@property (nonatomic, bm_lazy) DataLoader *dataLoader; 
@property (nonatomic, bm_partial) ErrorView *errorView; 
@end
Multiple Custom Attributes 
#import "ViewController.h" 
@implementation ViewController 
@lazy(dataLoader) 
@partial(errorView) 
- (void)viewDidLoad 
{ 
[super viewDidLoaded]; 
[self.dataLoader loadNextPage]; 
[self.view addSubview:self.errorView]; 
} 
@end
How to extend it
@property (nonatomic, bm_preference) NSString *cocoaHeads;
Module structure 
BloodMagic/Sources/Modules/Preference (master ✔) ➜ tree 
|-- Private 
| |-- BMPreferenceHook.h 
| |-- BMPreferenceHook.m 
| |-- BMPreferenceModuleLoader.h 
| `-- BMPreferenceModuleLoader.m 
`-- Public 
`-- BMPreference.h 
… 
|-- BloodMagic/Sources 
`-- Preference.h
Public Protocol 
@protocol BMPreference 
<NSObject> 
@end
Public Header 
#import <BloodMagic/Sources/Modules/Core/Public/BMPublicCoreDefnitions.h> 
#import <BloodMagic/Sources/Modules/Preference/Public/BMPreference.h> 
#ifndef bm_preference 
#define bm_preference 
#endif 
#ifndef preference 
#define preference(property_name) register_module(BMPreference, property_name) 
#endif
Public Header 
#import <BloodMagic/Sources/Modules/Core/Public/BMPublicCoreDefnitions.h> 
#import <BloodMagic/Sources/Modules/Preference/Public/BMPreference.h> 
#ifndef bm_preference 
#define bm_preference 
#endif 
#ifndef preference 
#define preference(property_name) register_module(BMPreference, property_name) 
#endif
Private Module Loader 
#import <Foundation/Foundation.h> 
@interface BMPreferenceModuleLoader : NSObject 
@end
Private Module Loader 
#import "BMPreferenceModuleLoader.h" 
#import "BMPreference.h" 
#import "BMBloodMagicInjector.h" 
@implementation BMPreferenceModuleLoader 
+ (void)load 
{ 
@autoreleasepool { 
BMBloodMagicInjector *injector = [BMBloodMagicInjector new]; 
[injector injectBloodMagicInto:@protocol(BMPreference)]; 
} 
} 
@end
Private Hook 
#import "BMHook.h" 
#import "BMPreference.h" 
@interface BMPreferenceHook : NSObject 
<BMHook, 
BMPreference> 
@end
Private Hook 
#import "BMPreferenceHook.h" 
#import "BMProperty.h" 
@implementation BMPreferenceHook 
static inline NSUserDefaults *bm_defaults() 
{ 
return [NSUserDefaults standardUserDefaults]; 
} 
+ (void)accessorHook:(id *)value 
withProperty:(const BMProperty *)property 
sender:(__unused id)sender 
{ 
*value = [bm_defaults() objectForKey:property.name]; 
} 
+ (void)mutatorHook:(id *)value 
withProperty:(const BMProperty *)property 
sender:(__unused id)sender 
{ 
[bm_defaults() setObject:*value forKey:property.name]; 
} 
@end
Private Hook 
Accessor 
static inline NSUserDefaults *bm_defaults() 
{ 
return [NSUserDefaults standardUserDefaults]; 
} 
+ (void)accessorHook:(id *)value 
withProperty:(const BMProperty *)property 
sender:(__unused id)sender 
{ 
*value = [bm_defaults() objectForKey:property.name]; 
}
Private Hook 
Mutator 
static inline NSUserDefaults *bm_defaults() 
{ 
return [NSUserDefaults standardUserDefaults]; 
} 
+ (void)mutatorHook:(id *)value 
withProperty:(const BMProperty *)property 
sender:(__unused id)sender 
{ 
[bm_defaults() setObject:*value forKey:property.name]; 
}
BMPreference Usage 
#import <BloodMagic/Preference.h> 
@interface Settings : NSObject 
<BMPreference> 
@property (nonatomic, bm_preference) NSString *name; 
@property (nonatomic, bm_preference) NSUInteger age; 
@end
BMPreference Usage 
#import "Settings.h" 
@implementation Settings 
@dynamic name; 
@dynamic age; 
@end
BMPreference Usage 
Settings *settings = [Settings new]; 
settings.name = @"AlexDenisov"; 
settings.age = 26; 
// … 
NSLog(@"%@", defaults);
BMPreference Usage 
Settings *settings = [Settings new]; 
settings.name = @"AlexDenisov"; 
settings.age = 26; 
// … 
NSLog(@"%@", defaults); 
{ 
… 
age = 26; 
name = AlexDenisov; 
… 
}
How does it work
BloodMagic is modular 
~/Projects/BloodMagic/Sources (master ✔) ➜ tree -L 2 
. 
`-- Modules 
|-- Core 
|-- Final 
|-- Injectable 
|-- Initializers 
|-- Lazy 
|-- Partial 
`-- Preference
BloodMagic is modular 
~/Projects/BloodMagic/Sources (master ✔) ➜ tree -L 2 
. 
`-- Modules 
|-- Core 
|-- Final 
|-- Injectable 
|-- Initializers 
|-- Lazy 
|-- Partial 
`-- Preference 
Property attributes 
implementation
BloodMagic is modular 
~/Projects/BloodMagic/Sources (master ✔) ➜ tree -L 2 
. 
`-- Modules 
|-- Core 
|-- Final 
|-- Injectable 
|-- Initializers 
|-- Lazy 
|-- Partial 
`-- Preference 
Low level logic 
• hooks 
• injections 
• runtime routines
Core Module: Hooks 
@protocol BMHook 
<NSObject> 
@optional 
+ (void)mutatorHook:(id *)value 
withProperty:(const BMProperty *)property 
sender:(id)sender; 
+ (void)accessorHook:(id *)value 
withProperty:(const BMProperty *)property 
sender:(id)sender; 
@end
Core Module: Injections 
@interface BMBloodMagicInjector : NSObject 
- (void)injectBloodMagicInto:(Protocol *)protocol; 
@end
Core Module: Injections 
@implementation BMBloodMagicInjector 
// pseudocode 
- (void)injectBloodMagicInto:(Protocol *)protocol 
{ 
class_list_t classes = collectClasses(protocol); 
property_list_t properties = collectDynamicProperties(classes); 
for (Property *property in properties) { 
Hook *hook = hookForProperty(property); 
property.accessor = hook.accessor; 
property.mutator = hook.mutator; 
} 
} 
@end
Sources: 
https://github.com/railsware/BloodMagic 
Blog-post: 
http://l.rw.rw/dibm 
Slides: 
https://speakerdeck.com/alexdenisov/bloodmagic 
https://speakerdeck.com/0xc010d/dependency-injection-ftw
Questions?

More Related Content

What's hot

What's Coming in Spring 3.0
What's Coming in Spring 3.0What's Coming in Spring 3.0
What's Coming in Spring 3.0Matt Raible
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworksdiego_k
 
Apache Hive Hook
Apache Hive HookApache Hive Hook
Apache Hive HookMinwoo Kim
 
Apollo ecosystem
Apollo ecosystemApollo ecosystem
Apollo ecosystemJames Akwuh
 
«От экспериментов с инфраструктурой до внедрения в продакшен»​
«От экспериментов с инфраструктурой до внедрения в продакшен»​«От экспериментов с инфраструктурой до внедрения в продакшен»​
«От экспериментов с инфраструктурой до внедрения в продакшен»​FDConf
 
OGSA-DAI DQP: A Developer's View
OGSA-DAI DQP: A Developer's ViewOGSA-DAI DQP: A Developer's View
OGSA-DAI DQP: A Developer's ViewBartosz Dobrzelecki
 
Read, store and create xml and json
Read, store and create xml and jsonRead, store and create xml and json
Read, store and create xml and jsonKim Berg Hansen
 
JAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJosé Paumard
 
Using the new WordPress REST API
Using the new WordPress REST APIUsing the new WordPress REST API
Using the new WordPress REST APICaldera Labs
 
Extending the WordPress REST API - Josh Pollock
Extending the WordPress REST API - Josh PollockExtending the WordPress REST API - Josh Pollock
Extending the WordPress REST API - Josh PollockCaldera Labs
 
Connecting Content Silos: One CMS, Many Sites With The WordPress REST API
 Connecting Content Silos: One CMS, Many Sites With The WordPress REST API Connecting Content Silos: One CMS, Many Sites With The WordPress REST API
Connecting Content Silos: One CMS, Many Sites With The WordPress REST APICaldera Labs
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to productionFDConf
 
Rails 6 frontend frameworks
Rails 6 frontend frameworksRails 6 frontend frameworks
Rails 6 frontend frameworksEric Guo
 
the Spring 4 update
the Spring 4 updatethe Spring 4 update
the Spring 4 updateJoshua Long
 

What's hot (20)

What's Coming in Spring 3.0
What's Coming in Spring 3.0What's Coming in Spring 3.0
What's Coming in Spring 3.0
 
Riding Apache Camel
Riding Apache CamelRiding Apache Camel
Riding Apache Camel
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
 
Apache Hive Hook
Apache Hive HookApache Hive Hook
Apache Hive Hook
 
JavaCro'14 - Scala and Java EE 7 Development Experiences – Peter Pilgrim
JavaCro'14 - Scala and Java EE 7 Development Experiences – Peter PilgrimJavaCro'14 - Scala and Java EE 7 Development Experiences – Peter Pilgrim
JavaCro'14 - Scala and Java EE 7 Development Experiences – Peter Pilgrim
 
Apollo ecosystem
Apollo ecosystemApollo ecosystem
Apollo ecosystem
 
«От экспериментов с инфраструктурой до внедрения в продакшен»​
«От экспериментов с инфраструктурой до внедрения в продакшен»​«От экспериментов с инфраструктурой до внедрения в продакшен»​
«От экспериментов с инфраструктурой до внедрения в продакшен»​
 
OGSA-DAI DQP: A Developer's View
OGSA-DAI DQP: A Developer's ViewOGSA-DAI DQP: A Developer's View
OGSA-DAI DQP: A Developer's View
 
Read, store and create xml and json
Read, store and create xml and jsonRead, store and create xml and json
Read, store and create xml and json
 
JAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) Bridge
 
JavaCro'14 - Unit testing in AngularJS – Slaven Tomac
JavaCro'14 - Unit testing in AngularJS – Slaven TomacJavaCro'14 - Unit testing in AngularJS – Slaven Tomac
JavaCro'14 - Unit testing in AngularJS – Slaven Tomac
 
Using the new WordPress REST API
Using the new WordPress REST APIUsing the new WordPress REST API
Using the new WordPress REST API
 
Extending the WordPress REST API - Josh Pollock
Extending the WordPress REST API - Josh PollockExtending the WordPress REST API - Josh Pollock
Extending the WordPress REST API - Josh Pollock
 
Connecting Content Silos: One CMS, Many Sites With The WordPress REST API
 Connecting Content Silos: One CMS, Many Sites With The WordPress REST API Connecting Content Silos: One CMS, Many Sites With The WordPress REST API
Connecting Content Silos: One CMS, Many Sites With The WordPress REST API
 
Reporting solutions for ADF Applications
Reporting solutions for ADF ApplicationsReporting solutions for ADF Applications
Reporting solutions for ADF Applications
 
Redux. From twitter hype to production
Redux. From twitter hype to productionRedux. From twitter hype to production
Redux. From twitter hype to production
 
Rails 6 frontend frameworks
Rails 6 frontend frameworksRails 6 frontend frameworks
Rails 6 frontend frameworks
 
the Spring 4 update
the Spring 4 updatethe Spring 4 update
the Spring 4 update
 
Java Server Pages
Java Server PagesJava Server Pages
Java Server Pages
 
Data Access with JDBC
Data Access with JDBCData Access with JDBC
Data Access with JDBC
 

Similar to Blood magic

How to replace rails asset pipeline with webpack?
How to replace rails asset pipeline with webpack?How to replace rails asset pipeline with webpack?
How to replace rails asset pipeline with webpack?Tomasz Bak
 
Web applications with Catalyst
Web applications with CatalystWeb applications with Catalyst
Web applications with Catalystsvilen.ivanov
 
Magento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowMagento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowVrann Tulika
 
Curscatalyst
CurscatalystCurscatalyst
CurscatalystKar Juan
 
Java Web Programming [5/9] : EL, JSTL and Custom Tags
Java Web Programming [5/9] : EL, JSTL and Custom TagsJava Web Programming [5/9] : EL, JSTL and Custom Tags
Java Web Programming [5/9] : EL, JSTL and Custom TagsIMC Institute
 
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdfdokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdfAppster1
 
dokumen.tips_rediscovering-spring-with-spring-boot1.pdf
dokumen.tips_rediscovering-spring-with-spring-boot1.pdfdokumen.tips_rediscovering-spring-with-spring-boot1.pdf
dokumen.tips_rediscovering-spring-with-spring-boot1.pdfAppster1
 
JavaServer Faces 2.0 - JavaOne India 2011
JavaServer Faces 2.0 - JavaOne India 2011JavaServer Faces 2.0 - JavaOne India 2011
JavaServer Faces 2.0 - JavaOne India 2011Arun Gupta
 
Rediscovering Spring with Spring Boot(1)
Rediscovering Spring with Spring Boot(1)Rediscovering Spring with Spring Boot(1)
Rediscovering Spring with Spring Boot(1)Gunith Devasurendra
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryTatsuhiko Miyagawa
 
Apache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei BatisApache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei Batisday
 
Laravel5 Introduction and essentials
Laravel5 Introduction and essentialsLaravel5 Introduction and essentials
Laravel5 Introduction and essentialsPramod Kadam
 
Network Automation: Ansible 102
Network Automation: Ansible 102Network Automation: Ansible 102
Network Automation: Ansible 102APNIC
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the TrenchesJonathan Wage
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenchesLukas Smith
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)Igor Bronovskyy
 

Similar to Blood magic (20)

How to replace rails asset pipeline with webpack?
How to replace rails asset pipeline with webpack?How to replace rails asset pipeline with webpack?
How to replace rails asset pipeline with webpack?
 
Web applications with Catalyst
Web applications with CatalystWeb applications with Catalyst
Web applications with Catalyst
 
Having Fun with Play
Having Fun with PlayHaving Fun with Play
Having Fun with Play
 
Magento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowMagento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request Flow
 
Curscatalyst
CurscatalystCurscatalyst
Curscatalyst
 
Java Web Programming [5/9] : EL, JSTL and Custom Tags
Java Web Programming [5/9] : EL, JSTL and Custom TagsJava Web Programming [5/9] : EL, JSTL and Custom Tags
Java Web Programming [5/9] : EL, JSTL and Custom Tags
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdfdokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
dokumen.tips_rediscovering-spring-with-spring-boot1 (1).pdf
 
dokumen.tips_rediscovering-spring-with-spring-boot1.pdf
dokumen.tips_rediscovering-spring-with-spring-boot1.pdfdokumen.tips_rediscovering-spring-with-spring-boot1.pdf
dokumen.tips_rediscovering-spring-with-spring-boot1.pdf
 
JavaServer Faces 2.0 - JavaOne India 2011
JavaServer Faces 2.0 - JavaOne India 2011JavaServer Faces 2.0 - JavaOne India 2011
JavaServer Faces 2.0 - JavaOne India 2011
 
Rediscovering Spring with Spring Boot(1)
Rediscovering Spring with Spring Boot(1)Rediscovering Spring with Spring Boot(1)
Rediscovering Spring with Spring Boot(1)
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
 
Apache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei BatisApache Con Us2007 Apachei Batis
Apache Con Us2007 Apachei Batis
 
Laravel5 Introduction and essentials
Laravel5 Introduction and essentialsLaravel5 Introduction and essentials
Laravel5 Introduction and essentials
 
Network Automation: Ansible 102
Network Automation: Ansible 102Network Automation: Ansible 102
Network Automation: Ansible 102
 
Let's react - Meetup
Let's react - MeetupLet's react - Meetup
Let's react - Meetup
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
 
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
09 - express nodes on the right angle - vitaliy basyuk - it event 2013 (5)
 

Recently uploaded

%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benonimasabamasaba
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Bert Jan Schrijver
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareJim McKeeth
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...chiefasafspells
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...masabamasaba
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfonteinmasabamasaba
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2
 
tonesoftg
tonesoftgtonesoftg
tonesoftglanshi9
 

Recently uploaded (20)

%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
WSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security ProgramWSO2CON 2024 - How to Run a Security Program
WSO2CON 2024 - How to Run a Security Program
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 

Blood magic

  • 1. BloodMagic Custom property attributes CocoaHeads, 2014
  • 2. WHOAMI Github: AlexDenisov IRC: AlexDenisov 1101_debian Twitter:
  • 3. Outline • What BloodMagic is • How to use it • How to extend it • How does it work • Q & A
  • 5. Problem @interface ViewController : UIViewController @property (nonatomic) NSMutableArray *resources; @property (nonatomic) ProgressView *progressView; @property (nonatomic) ErrorView *errorView; @property (nonatomic) DataLoader *dataLoader; @end
  • 6. Lazy Initialization @implementation ViewController - (NSMutableArray *)resources { if (!_resources) { _resources = [NSMutableArray new]; } return _resources; } - (ProgressView *)progressView { if (!_progressView) { _progressView = [ProgressView new]; } return _progressView; } - (ErrorView *)errorView { if (!_errorView) { _errorView = [ErrorView new]; } return _errorView; } - (DataLoader *)dataLoader { if (!_dataLoader) { _dataLoader = [DataLoader new]; } return _dataLoader; } @end
  • 7. - (PropertyClass *)propertyName { if (!_propertyName) { _propertyName = [PropertyClass new]; } return _propertyName; } A lot of Boilerplate Code
  • 8. Just add ‘lazy’ attribute @interface ViewController : UIViewController @property (nonatomic, lazy) NSMutableArray *resources; @property (nonatomic, lazy) CenterProgress *centerProgress; @property (nonatomic, lazy) BottomProgress *bottomProgress; @property (nonatomic, lazy) DataLoader *dataLoader; @end
  • 9. Just add ‘lazy’ attribute @interface ViewController : UIViewController @property (nonatomic, lazy) NSMutableArray *resources; @property (nonatomic, lazy) CenterProgress *centerProgress; @property (nonatomic, lazy) BottomProgress *bottomProgress; @property (nonatomic, lazy) DataLoader *dataLoader; @end /tmp/lazy_test ➜ make … error: unknown property attribute 'lazy' @property (nonatomic, lazy) NSMutableArray *resources; ^ …
  • 10. BloodMagic a mechanism for creating custom property attributes based on your code
  • 11. Let’s add magic #import <BloodMagic/Lazy.h> @interface ViewController : UIViewController <BMLazy> @property (nonatomic) NSMutableArray *resources; @property (nonatomic) ProgressView *progressView; @property (nonatomic) ErrorView *errorView; @property (nonatomic) DataLoader *dataLoader; @end
  • 12. Let’s add magic @implementation ViewController @dynamic resources; @dynamic progressView; @dynamic errorView; @dynamic dataLoader; - (void)actOnSomething { [self.dataLoader loadNextPage]; // ^ new object created } @end
  • 13. Magic Happened @implementation ViewController @dynamic resources; @dynamic progressView; @dynamic errorView; @dynamic dataLoader; @end BloodMagic @implementation ViewController - (NSMutableArray *)resources { if (!_resources) { _resources = [NSMutableArray new]; } return _resources; } - (ProgressView *)progressView { if (!_progressView) { _progressView = [ProgressView new]; } return _progressView; } - (ErrorView *)errorView { if (!_errorView) { _errorView = [ErrorView new]; } return _errorView; } - (DataLoader *)dataLoader { if (!_dataLoader) { _dataLoader = [DataLoader new]; } return _dataLoader; } @end
  • 14. How to use BloodMagic
  • 15. Single Custom Attribute #import <BloodMagic/Lazy.h> @interface ViewController : UIViewController <BMLazy> @property (nonatomic, bm_lazy) DataLoader *dataLoader; @end
  • 16. Single Custom Attribute #import "ViewController.h" @implementation ViewController @dynamic dataLoader; - (void)viewDidLoad { [super viewDidLoad]; [self.dataLoader loadNextPage]; } @end
  • 17. Single Custom Attribute #import "ViewController.h" @implementation ViewController @dynamic dataLoader; - (void)viewDidLoad { [super viewDidLoad]; [self.dataLoader loadNextPage]; // ^ new object created } @end
  • 18. Multiple Custom Attributes #import <BloodMagic/Lazy.h> #import <BloodMagic/Partial.h> @interface ViewController : UIViewController <BMLazy, BMPartial> @property (nonatomic, bm_lazy) DataLoader *dataLoader; @property (nonatomic, bm_partial) ErrorView *errorView; @end
  • 19. Multiple Custom Attributes #import "ViewController.h" @implementation ViewController @lazy(dataLoader) @partial(errorView) - (void)viewDidLoad { [super viewDidLoaded]; [self.dataLoader loadNextPage]; [self.view addSubview:self.errorView]; } @end
  • 21. @property (nonatomic, bm_preference) NSString *cocoaHeads;
  • 22. Module structure BloodMagic/Sources/Modules/Preference (master ✔) ➜ tree |-- Private | |-- BMPreferenceHook.h | |-- BMPreferenceHook.m | |-- BMPreferenceModuleLoader.h | `-- BMPreferenceModuleLoader.m `-- Public `-- BMPreference.h … |-- BloodMagic/Sources `-- Preference.h
  • 23. Public Protocol @protocol BMPreference <NSObject> @end
  • 24. Public Header #import <BloodMagic/Sources/Modules/Core/Public/BMPublicCoreDefnitions.h> #import <BloodMagic/Sources/Modules/Preference/Public/BMPreference.h> #ifndef bm_preference #define bm_preference #endif #ifndef preference #define preference(property_name) register_module(BMPreference, property_name) #endif
  • 25. Public Header #import <BloodMagic/Sources/Modules/Core/Public/BMPublicCoreDefnitions.h> #import <BloodMagic/Sources/Modules/Preference/Public/BMPreference.h> #ifndef bm_preference #define bm_preference #endif #ifndef preference #define preference(property_name) register_module(BMPreference, property_name) #endif
  • 26. Private Module Loader #import <Foundation/Foundation.h> @interface BMPreferenceModuleLoader : NSObject @end
  • 27. Private Module Loader #import "BMPreferenceModuleLoader.h" #import "BMPreference.h" #import "BMBloodMagicInjector.h" @implementation BMPreferenceModuleLoader + (void)load { @autoreleasepool { BMBloodMagicInjector *injector = [BMBloodMagicInjector new]; [injector injectBloodMagicInto:@protocol(BMPreference)]; } } @end
  • 28. Private Hook #import "BMHook.h" #import "BMPreference.h" @interface BMPreferenceHook : NSObject <BMHook, BMPreference> @end
  • 29. Private Hook #import "BMPreferenceHook.h" #import "BMProperty.h" @implementation BMPreferenceHook static inline NSUserDefaults *bm_defaults() { return [NSUserDefaults standardUserDefaults]; } + (void)accessorHook:(id *)value withProperty:(const BMProperty *)property sender:(__unused id)sender { *value = [bm_defaults() objectForKey:property.name]; } + (void)mutatorHook:(id *)value withProperty:(const BMProperty *)property sender:(__unused id)sender { [bm_defaults() setObject:*value forKey:property.name]; } @end
  • 30. Private Hook Accessor static inline NSUserDefaults *bm_defaults() { return [NSUserDefaults standardUserDefaults]; } + (void)accessorHook:(id *)value withProperty:(const BMProperty *)property sender:(__unused id)sender { *value = [bm_defaults() objectForKey:property.name]; }
  • 31. Private Hook Mutator static inline NSUserDefaults *bm_defaults() { return [NSUserDefaults standardUserDefaults]; } + (void)mutatorHook:(id *)value withProperty:(const BMProperty *)property sender:(__unused id)sender { [bm_defaults() setObject:*value forKey:property.name]; }
  • 32. BMPreference Usage #import <BloodMagic/Preference.h> @interface Settings : NSObject <BMPreference> @property (nonatomic, bm_preference) NSString *name; @property (nonatomic, bm_preference) NSUInteger age; @end
  • 33. BMPreference Usage #import "Settings.h" @implementation Settings @dynamic name; @dynamic age; @end
  • 34. BMPreference Usage Settings *settings = [Settings new]; settings.name = @"AlexDenisov"; settings.age = 26; // … NSLog(@"%@", defaults);
  • 35. BMPreference Usage Settings *settings = [Settings new]; settings.name = @"AlexDenisov"; settings.age = 26; // … NSLog(@"%@", defaults); { … age = 26; name = AlexDenisov; … }
  • 36. How does it work
  • 37. BloodMagic is modular ~/Projects/BloodMagic/Sources (master ✔) ➜ tree -L 2 . `-- Modules |-- Core |-- Final |-- Injectable |-- Initializers |-- Lazy |-- Partial `-- Preference
  • 38. BloodMagic is modular ~/Projects/BloodMagic/Sources (master ✔) ➜ tree -L 2 . `-- Modules |-- Core |-- Final |-- Injectable |-- Initializers |-- Lazy |-- Partial `-- Preference Property attributes implementation
  • 39. BloodMagic is modular ~/Projects/BloodMagic/Sources (master ✔) ➜ tree -L 2 . `-- Modules |-- Core |-- Final |-- Injectable |-- Initializers |-- Lazy |-- Partial `-- Preference Low level logic • hooks • injections • runtime routines
  • 40. Core Module: Hooks @protocol BMHook <NSObject> @optional + (void)mutatorHook:(id *)value withProperty:(const BMProperty *)property sender:(id)sender; + (void)accessorHook:(id *)value withProperty:(const BMProperty *)property sender:(id)sender; @end
  • 41. Core Module: Injections @interface BMBloodMagicInjector : NSObject - (void)injectBloodMagicInto:(Protocol *)protocol; @end
  • 42. Core Module: Injections @implementation BMBloodMagicInjector // pseudocode - (void)injectBloodMagicInto:(Protocol *)protocol { class_list_t classes = collectClasses(protocol); property_list_t properties = collectDynamicProperties(classes); for (Property *property in properties) { Hook *hook = hookForProperty(property); property.accessor = hook.accessor; property.mutator = hook.mutator; } } @end
  • 43. Sources: https://github.com/railsware/BloodMagic Blog-post: http://l.rw.rw/dibm Slides: https://speakerdeck.com/alexdenisov/bloodmagic https://speakerdeck.com/0xc010d/dependency-injection-ftw