Skip to content
This repository has been archived by the owner on Jun 19, 2019. It is now read-only.

Commit

Permalink
Merge pull request #1 from wearezeta/feature/binary-cas
Browse files Browse the repository at this point in the history
Classy caching
  • Loading branch information
mikeger committed Mar 11, 2016
2 parents b756f0f + e0b7627 commit b27bae3
Show file tree
Hide file tree
Showing 22 changed files with 292 additions and 44 deletions.
2 changes: 2 additions & 0 deletions Classy/Classy.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@
#import "UINavigationBar+CASAdditions.h"
#import "UITabBar+CASAdditions.h"
#import "UIToolbar+CASAdditions.h"
#import "UIViewController+CASAdditions.h"
#import "UINavigationItem+CASAdditions.h"
16 changes: 16 additions & 0 deletions Classy/Parser/CASDeviceOSVersionItem.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,20 @@ - (NSString *)stringValue {
return [NSString stringWithFormat:@"(version:%@%@)", [CASDeviceSelector stringFromRelation:self.relation], self.version];
}

#pragma mark - NSCoding

- (id)initWithCoder:(NSCoder *)aDecoder {
self = [self init];
if (nil != self) {
self.relation = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(relation))];
self.version = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(version))];
}
return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeInteger:self.relation forKey:NSStringFromSelector(@selector(relation))];
[aCoder encodeObject:self.version forKey:NSStringFromSelector(@selector(version))];
}

@end
2 changes: 1 addition & 1 deletion Classy/Parser/CASDeviceScreenSizeItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
@property (nonatomic, assign) CASRelation relation;
@property(nonatomic, assign) CASDeviceSelectorScreenDimension dimension;

@end
@end
23 changes: 19 additions & 4 deletions Classy/Parser/CASDeviceScreenSizeItem.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@

#import "CASDeviceScreenSizeItem.h"

@implementation CASDeviceScreenSizeItem {

}
@implementation CASDeviceScreenSizeItem

- (BOOL)isValid {
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
Expand Down Expand Up @@ -41,5 +39,22 @@ - (NSString *)stringValue {
return [NSString stringWithFormat:@"(screen-%@:%@%.0f)", dimensionString, [CASDeviceSelector stringFromRelation:self.relation], self.value];
}

#pragma mark - NSCoding

- (id)initWithCoder:(NSCoder *)aDecoder {
self = [self init];
if (nil != self) {
self.relation = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(relation))];
self.value = [aDecoder decodeFloatForKey:NSStringFromSelector(@selector(value))];
self.dimension = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(dimension))];
}
return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeInteger:self.relation forKey:NSStringFromSelector(@selector(relation))];
[aCoder encodeFloat:self.value forKey:NSStringFromSelector(@selector(value))];
[aCoder encodeInteger:self.dimension forKey:NSStringFromSelector(@selector(dimension))];
}

@end
@end
2 changes: 1 addition & 1 deletion Classy/Parser/CASDeviceSelector.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ typedef NS_ENUM(NSUInteger, CASDeviceSelectorScreenDimension) {
CASDeviceSelectorScreenDimensionHeight,
};

@interface CASDeviceSelector : NSObject
@interface CASDeviceSelector : NSObject <NSCoding>

@property (nonatomic, strong, readonly) NSArray *items;

Expand Down
14 changes: 14 additions & 0 deletions Classy/Parser/CASDeviceSelector.m
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,18 @@ + (NSString *)stringFromRelation:(CASRelation)relation {
}
}

#pragma mark - NSCoding

- (id)initWithCoder:(NSCoder *)aDecoder {
self = [self init];
if (nil != self) {
_items = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(items))];
}
return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.items forKey:NSStringFromSelector(@selector(items))];
}

@end
4 changes: 2 additions & 2 deletions Classy/Parser/CASDeviceSelectorItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ typedef NS_ENUM(NSInteger, CASRelation) {
CASRelationUndefined = NSNotFound,
};

@protocol CASDeviceSelectorItem <NSObject>
@protocol CASDeviceSelectorItem <NSObject, NSCoding>

- (BOOL)isValid;
- (NSString *)stringValue;

@end
@end
14 changes: 14 additions & 0 deletions Classy/Parser/CASDeviceTypeItem.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,18 @@ - (NSString *)stringValue {
return @"pad";
}

#pragma mark - NSCoding

- (id)initWithCoder:(NSCoder *)aDecoder {
self = [self init];
if (nil != self) {
self.deviceType = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(deviceType))];
}
return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeInteger:self.deviceType forKey:NSStringFromSelector(@selector(deviceType))];
}

@end
2 changes: 1 addition & 1 deletion Classy/Parser/CASStyleNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#import "CASStyleSelector.h"
#import "CASDeviceSelector.h"

@interface CASStyleNode : NSObject
@interface CASStyleNode : NSObject <NSCoding>

/**
* NSInvocations to apply to appropriate view
Expand Down
19 changes: 19 additions & 0 deletions Classy/Parser/CASStyleNode.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,23 @@ - (void)addStyleProperty:(CASStyleProperty *)styleProperty {
[_styleProperties addObject:styleProperty];
}

#pragma mark - NSCoding

- (id)initWithCoder:(NSCoder *)aDecoder {
self = [self init];
if (nil != self) {
self.invocations = nil;
_styleProperties = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(styleProperties))];
self.styleSelector = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(styleSelector))];
self.deviceSelector = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(deviceSelector))];
}
return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.styleProperties forKey:NSStringFromSelector(@selector(styleProperties))];
[aCoder encodeObject:self.styleSelector forKey:NSStringFromSelector(@selector(styleSelector))];
[aCoder encodeObject:self.deviceSelector forKey:NSStringFromSelector(@selector(deviceSelector))];
}

@end
4 changes: 2 additions & 2 deletions Classy/Parser/CASStyleProperty.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#import <UIKit/UIKit.h>
#import "CASToken.h"

@interface CASStyleProperty : NSObject
@interface CASStyleProperty : NSObject <NSCoding>

/**
* Name of the receiver
Expand Down Expand Up @@ -44,7 +44,7 @@
@property (nonatomic, strong) NSDictionary *arguments;

/**
* Creates property with raw data in the form of CATokens
* Creates property with raw data in the form of CASTokens
*/
- (id)initWithNameToken:(CASToken *)nameToken valueTokens:(NSArray *)valueTokens;

Expand Down
24 changes: 24 additions & 0 deletions Classy/Parser/CASStyleProperty.m
Original file line number Diff line number Diff line change
Expand Up @@ -350,4 +350,28 @@ - (void)addChildStyleProperty:(CASStyleProperty *)styleProperty {
[_childStyleProperties addObject:styleProperty];
}

#pragma mark - NSCoding

- (id)initWithCoder:(NSCoder *)aDecoder {
self = [self init];
if (nil != self) {
self.name = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(name))];
self.values = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(values))];
self.nameToken = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(nameToken))];
self.valueTokens = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(valueTokens))];
_childStyleProperties = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(childStyleProperties))];
self.arguments = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(arguments))];
}
return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.name forKey:NSStringFromSelector(@selector(name))];
[aCoder encodeObject:self.values forKey:NSStringFromSelector(@selector(values))];
[aCoder encodeObject:self.nameToken forKey:NSStringFromSelector(@selector(nameToken))];
[aCoder encodeObject:self.valueTokens forKey:NSStringFromSelector(@selector(valueTokens))];
[aCoder encodeObject:_childStyleProperties forKey:NSStringFromSelector(@selector(childStyleProperties))];
[aCoder encodeObject:self.arguments forKey:NSStringFromSelector(@selector(arguments))];
}

@end
2 changes: 1 addition & 1 deletion Classy/Parser/CASStyleSelector.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#import <UIKit/UIKit.h>
#import "CASStyleableItem.h"

@interface CASStyleSelector : NSObject <NSCopying>
@interface CASStyleSelector : NSObject <NSCopying, NSCoding>

/**
* Class of View to match
Expand Down
30 changes: 30 additions & 0 deletions Classy/Parser/CASStyleSelector.m
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,34 @@ - (BOOL)matchesItem:(id<CASStyleableItem>)item {
return YES;
}

#pragma mark - NSCoding

- (id)initWithCoder:(NSCoder *)aDecoder {
self = [self init];

if (nil != self) {
self.objectClass = NSClassFromString([aDecoder decodeObjectForKey:NSStringFromSelector(@selector(objectClass))]);
self.styleClass = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(styleClass))];
self.shouldSelectSubclasses = [aDecoder decodeBoolForKey:NSStringFromSelector(@selector(shouldSelectSubclasses))];
self.shouldSelectIndirectSuperview = [aDecoder decodeBoolForKey:NSStringFromSelector(@selector(shouldSelectIndirectSuperview))];
self.parent = [aDecoder decodeBoolForKey:NSStringFromSelector(@selector(isParent))];
self.shouldConcatToParent = [aDecoder decodeBoolForKey:NSStringFromSelector(@selector(shouldConcatToParent))];
self.arguments = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(arguments))];
self.parentSelector = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(parentSelector))];
}

return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:NSStringFromClass(self.objectClass) forKey:NSStringFromSelector(@selector(objectClass))];
[aCoder encodeObject:self.styleClass forKey:NSStringFromSelector(@selector(styleClass))];
[aCoder encodeBool:self.shouldSelectSubclasses forKey:NSStringFromSelector(@selector(shouldSelectSubclasses))];
[aCoder encodeBool:self.shouldSelectIndirectSuperview forKey:NSStringFromSelector(@selector(shouldSelectIndirectSuperview))];
[aCoder encodeBool:self.parent forKey:NSStringFromSelector(@selector(isParent))];
[aCoder encodeBool:self.shouldConcatToParent forKey:NSStringFromSelector(@selector(shouldConcatToParent))];
[aCoder encodeObject:self.arguments forKey:NSStringFromSelector(@selector(arguments))];
[aCoder encodeObject:self.parentSelector forKey:NSStringFromSelector(@selector(parentSelector))];
}

@end
22 changes: 22 additions & 0 deletions Classy/Parser/CASStyler.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,26 @@
#import "CASObjectClassDescriptor.h"
#import "CASStyleableItem.h"

@class CASStyleNode;

/**
* Protocol caching the @c CASStyleNode's. Adds the possibility to cache the in-memory representation of Classy's CAS
* file, since parsing the file is slower than loading cached version.
*/
@protocol CASCacheProtocol <NSObject>
@optional
/**
* Loads cached version of stylesheet located at @c path with @c variables
*/
- (NSArray <CASStyleNode *> *)cachedStyleNodesFromCASPath:(NSString *)path withVariables:(NSDictionary *)variables;

/**
* Stores the stylesheet in-memory representation loaded from @c path with @c variables
*/
- (void)cacheStyleNodes:(NSArray <CASStyleNode *> *)styleNodes fromPath:(NSString *)path variables:(NSDictionary *)variables;
@end


@interface CASStyler : NSObject

+ (void)bootstrapClassyWithTargetWindows:(NSArray *)targetWindows;
Expand All @@ -19,6 +39,8 @@
*/
+ (instancetype)defaultStyler;

@property (nonatomic, weak) id<CASCacheProtocol> cache;

@property (nonatomic, copy) NSDictionary *variables;

/**
Expand Down
54 changes: 36 additions & 18 deletions Classy/Parser/CASStyler.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
return result;
}


@interface CASStyler ()

@property (nonatomic, strong) NSMutableArray *styleNodes;
Expand Down Expand Up @@ -156,41 +157,58 @@ - (void)setFilePath:(NSString *)filePath error:(NSError **)error {
self.styleClassIndex = [NSMutableDictionary new];
self.objectClassIndex = [NSMutableDictionary new];

CASParser *parser = [CASParser parserFromFilePath:filePath variables:self.variables error:error];
NSArray *styleNodes = parser.styleNodes;
NSArray *styleNodes = nil;
NSSet *importedFileNames = nil;

if ([self.cache respondsToSelector:@selector(cachedStyleNodesFromCASPath:withVariables:)]) {
styleNodes = [self.cache cachedStyleNodesFromCASPath:filePath withVariables:self.variables];
}

if (styleNodes != nil) {
importedFileNames = [NSSet set];
self.styleNodes = [NSMutableArray arrayWithArray:styleNodes];
}
else {
CASParser *parser = [CASParser parserFromFilePath:filePath variables:self.variables error:error];
styleNodes = parser.styleNodes;
importedFileNames = parser.importedFileNames;

self.styleNodes = [self validNodes:styleNodes];

// order ascending by precedence
[self.styleNodes sortWithOptions:NSSortStable usingComparator:^NSComparisonResult(CASStyleNode *n1, CASStyleNode *n2) {
NSInteger precedence1 = [n1.styleSelector precedence];
NSInteger precedence2 = [n2.styleSelector precedence];
if (precedence2 > precedence1) {
return NSOrderedAscending;
} else if (precedence2 < precedence1) {
return NSOrderedDescending;
}
return NSOrderedSame;
}];

if ([self.cache respondsToSelector:@selector(cacheStyleNodes:fromPath:variables:)]) {
[self.cache cacheStyleNodes:styleNodes fromPath:filePath variables:self.variables];
}
}

if (self.watchFilePath) {
for (dispatch_source_t source in self.fileWatchers) {
dispatch_source_cancel(source);
}
[self.fileWatchers removeAllObjects];
[self reloadOnChangesToFilePath:self.watchFilePath];
NSString *directoryPath = [self.watchFilePath stringByDeletingLastPathComponent];
for (NSString *fileName in parser.importedFileNames) {
for (NSString *fileName in importedFileNames) {
NSString *resolvedPath = [directoryPath stringByAppendingPathComponent:fileName];
[self reloadOnChangesToFilePath:resolvedPath];
}
}


if (!styleNodes.count) {
return;
}

self.styleNodes = [self validNodes:styleNodes];

// order ascending by precedence
[self.styleNodes sortWithOptions:NSSortStable usingComparator:^NSComparisonResult(CASStyleNode *n1, CASStyleNode *n2) {
NSInteger precedence1 = [n1.styleSelector precedence];
NSInteger precedence2 = [n2.styleSelector precedence];
if (precedence2 > precedence1) {
return NSOrderedAscending;
} else if (precedence2 < precedence1) {
return NSOrderedDescending;
}
return NSOrderedSame;
}];

[self populateStyleLookupTables:self.styleNodes];

self.invocationObjectArguments = NSMutableArray.new;
Expand Down
2 changes: 1 addition & 1 deletion Classy/Parser/CASToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ typedef NS_ENUM(NSInteger, CASTokenType) {
CASTokenTypeSelector,
};

@interface CASToken : NSObject
@interface CASToken : NSObject <NSCoding>

/**
* The type of the token, may not represent the true type which is determined in context of other tokens
Expand Down
Loading

0 comments on commit b27bae3

Please sign in to comment.