-
Notifications
You must be signed in to change notification settings - Fork 193
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add categories on UILabel, UITextView, and UITextField to accept a ch…
…ainable object.
- Loading branch information
1 parent
30ba7f9
commit d1864be
Showing
12 changed files
with
578 additions
and
0 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
// | ||
// BONUtilitiesTestCase.m | ||
// BonMot | ||
// | ||
// Created by Nora Trapp on 3/3/16. | ||
// | ||
// | ||
|
||
#import "BONBaseTestCase.h" | ||
|
||
@import BonMot; | ||
|
||
@interface BONUtilitiesTestCase : BONBaseTestCase | ||
|
||
@end | ||
|
||
@implementation BONUtilitiesTestCase | ||
|
||
#pragma mark - UILabel | ||
|
||
- (void)testLabelTextAfterChainable | ||
{ | ||
UILabel *label = UILabel.new; | ||
label.bonChainable = BONChain.new.font([UIFont systemFontOfSize:16]); | ||
label.text = @"Hello, world!"; | ||
|
||
XCTAssertEqualObjects(label.attributedText.string, @"Hello, world!"); | ||
|
||
NSParagraphStyle *defaultParagraphStyle = [[NSParagraphStyle alloc] init]; | ||
|
||
NSDictionary *controlAttributes = @{ | ||
BONValueFromRange(0, 13) : @{ | ||
NSParagraphStyleAttributeName : defaultParagraphStyle, | ||
NSFontAttributeName : [UIFont systemFontOfSize:16], | ||
}, | ||
}; | ||
|
||
BONAssertAttributedStringHasAttributes(label.attributedText, controlAttributes); | ||
} | ||
|
||
- (void)testLabelTextBeforeChainable | ||
{ | ||
UILabel *label = UILabel.new; | ||
label.text = @"Hello, world!"; | ||
label.bonChainable = BONChain.new.font([UIFont systemFontOfSize:16]); | ||
|
||
XCTAssertEqualObjects(label.attributedText.string, @"Hello, world!"); | ||
|
||
NSParagraphStyle *defaultParagraphStyle = [[NSParagraphStyle alloc] init]; | ||
|
||
NSDictionary *controlAttributes = @{ | ||
BONValueFromRange(0, 13) : @{ | ||
NSParagraphStyleAttributeName : defaultParagraphStyle, | ||
NSFontAttributeName : [UIFont systemFontOfSize:16], | ||
}, | ||
}; | ||
|
||
BONAssertAttributedStringHasAttributes(label.attributedText, controlAttributes); | ||
} | ||
|
||
- (void)testLabelAttributedTextAfterChainable | ||
{ | ||
UILabel *label = UILabel.new; | ||
label.bonChainable = BONChain.new.font([UIFont systemFontOfSize:16]); | ||
label.attributedText = [[NSAttributedString alloc] initWithString:@"Hello, world!"]; | ||
|
||
XCTAssertNil(label.bonChainable); | ||
XCTAssertEqualObjects(label.attributedText.string, @"Hello, world!"); | ||
|
||
NSDictionary *controlAttributes = [self defaultAttributesForClass:[UILabel class] withString:@"Hello, world!"]; | ||
|
||
BONAssertAttributedStringHasAttributes(label.attributedText, controlAttributes); | ||
} | ||
|
||
- (void)testLabelAttributedTextBeforeChainable | ||
{ | ||
UILabel *label = UILabel.new; | ||
label.attributedText = [[NSAttributedString alloc] initWithString:@"Hello, world!"]; | ||
label.bonChainable = BONChain.new.font([UIFont systemFontOfSize:16]); | ||
|
||
XCTAssertNotNil(label.bonChainable); | ||
XCTAssertEqualObjects(label.attributedText.string, @"Hello, world!"); | ||
|
||
NSParagraphStyle *defaultParagraphStyle = [[NSParagraphStyle alloc] init]; | ||
|
||
NSDictionary *controlAttributes = @{ | ||
BONValueFromRange(0, 13) : @{ | ||
NSParagraphStyleAttributeName : defaultParagraphStyle, | ||
NSFontAttributeName : [UIFont systemFontOfSize:16], | ||
}, | ||
}; | ||
|
||
BONAssertAttributedStringHasAttributes(label.attributedText, controlAttributes); | ||
} | ||
|
||
#pragma mark - UITextView | ||
|
||
- (void)testTextViewTextAfterChainable | ||
{ | ||
UITextView *textView = UITextView.new; | ||
textView.bonChainable = BONChain.new.font([UIFont systemFontOfSize:16]); | ||
textView.text = @"Hello, world!"; | ||
|
||
XCTAssertEqualObjects(textView.attributedText.string, @"Hello, world!"); | ||
|
||
NSParagraphStyle *defaultParagraphStyle = [[NSParagraphStyle alloc] init]; | ||
|
||
NSDictionary *controlAttributes = @{ | ||
BONValueFromRange(0, 13) : @{ | ||
NSParagraphStyleAttributeName : defaultParagraphStyle, | ||
NSFontAttributeName : [UIFont systemFontOfSize:16], | ||
}, | ||
}; | ||
|
||
BONAssertAttributedStringHasAttributes(textView.attributedText, controlAttributes); | ||
} | ||
|
||
- (void)testTextViewTextBeforeChainable | ||
{ | ||
UITextView *textView = UITextView.new; | ||
textView.text = @"Hello, world!"; | ||
textView.bonChainable = BONChain.new.font([UIFont systemFontOfSize:16]); | ||
|
||
XCTAssertEqualObjects(textView.attributedText.string, @"Hello, world!"); | ||
|
||
NSParagraphStyle *defaultParagraphStyle = [[NSParagraphStyle alloc] init]; | ||
|
||
NSDictionary *controlAttributes = @{ | ||
BONValueFromRange(0, 13) : @{ | ||
NSParagraphStyleAttributeName : defaultParagraphStyle, | ||
NSFontAttributeName : [UIFont systemFontOfSize:16], | ||
}, | ||
}; | ||
|
||
BONAssertAttributedStringHasAttributes(textView.attributedText, controlAttributes); | ||
} | ||
|
||
- (void)testTextViewAttributedTextAfterChainable | ||
{ | ||
UITextView *textView = UITextView.new; | ||
textView.bonChainable = BONChain.new.font([UIFont systemFontOfSize:16]); | ||
textView.attributedText = [[NSAttributedString alloc] initWithString:@"Hello, world!"]; | ||
|
||
XCTAssertEqualObjects(textView.attributedText.string, @"Hello, world!"); | ||
|
||
NSDictionary *controlAttributes = [self defaultAttributesForClass:[UITextView class] withString:@"Hello, world!"]; | ||
|
||
BONAssertAttributedStringHasAttributes(textView.attributedText, controlAttributes); | ||
} | ||
|
||
- (void)testTextViewAttributedTextBeforeChainable | ||
{ | ||
UITextView *textView = UITextView.new; | ||
textView.attributedText = [[NSAttributedString alloc] initWithString:@"Hello, world!"]; | ||
textView.bonChainable = BONChain.new.font([UIFont systemFontOfSize:16]); | ||
|
||
XCTAssertEqualObjects(textView.attributedText.string, @"Hello, world!"); | ||
|
||
NSParagraphStyle *defaultParagraphStyle = [[NSParagraphStyle alloc] init]; | ||
|
||
NSDictionary *controlAttributes = @{ | ||
BONValueFromRange(0, 13) : @{ | ||
NSParagraphStyleAttributeName : defaultParagraphStyle, | ||
NSFontAttributeName : [UIFont systemFontOfSize:16], | ||
}, | ||
}; | ||
|
||
BONAssertAttributedStringHasAttributes(textView.attributedText, controlAttributes); | ||
} | ||
|
||
#pragma mark - UITextField | ||
|
||
- (void)testTextFieldTextAfterChainable | ||
{ | ||
UITextField *textField = UITextField.new; | ||
textField.bonChainable = BONChain.new.font([UIFont systemFontOfSize:16]); | ||
textField.text = @"Hello, world!"; | ||
|
||
XCTAssertEqualObjects(textField.attributedText.string, @"Hello, world!"); | ||
|
||
NSMutableDictionary *controlAttributes = [self defaultAttributesForClass:[UITextField class] withString:@"Hello, world!"]; | ||
[controlAttributes[BONValueFromRange(0, 13)] addEntriesFromDictionary:@{ | ||
NSFontAttributeName : [UIFont systemFontOfSize:16], | ||
}]; | ||
|
||
BONAssertAttributedStringHasAttributes(textField.attributedText, controlAttributes); | ||
} | ||
|
||
- (void)testTextFieldTextBeforeChainable | ||
{ | ||
UITextField *textField = UITextField.new; | ||
textField.text = @"Hello, world!"; | ||
textField.bonChainable = BONChain.new.font([UIFont systemFontOfSize:16]); | ||
|
||
XCTAssertEqualObjects(textField.attributedText.string, @"Hello, world!"); | ||
|
||
NSMutableDictionary *controlAttributes = [self defaultAttributesForClass:[UITextField class] withString:@"Hello, world!"]; | ||
[controlAttributes[BONValueFromRange(0, 13)] addEntriesFromDictionary:@{ | ||
NSFontAttributeName : [UIFont systemFontOfSize:16], | ||
}]; | ||
|
||
BONAssertAttributedStringHasAttributes(textField.attributedText, controlAttributes); | ||
} | ||
|
||
- (void)testTextFieldAttributedTextAfterChainable | ||
{ | ||
UITextField *textField = UITextField.new; | ||
textField.bonChainable = BONChain.new.font([UIFont systemFontOfSize:16]); | ||
textField.attributedText = [[NSAttributedString alloc] initWithString:@"Hello, world!"]; | ||
|
||
XCTAssertNil(textField.bonChainable); | ||
XCTAssertEqualObjects(textField.attributedText.string, @"Hello, world!"); | ||
|
||
NSDictionary *controlAttributes = [self defaultAttributesForClass:[UITextField class] withString:@"Hello, world!"]; | ||
|
||
BONAssertAttributedStringHasAttributes(textField.attributedText, controlAttributes); | ||
} | ||
|
||
- (void)testTextFieldAttributedTextBeforeChainable | ||
{ | ||
UITextField *textField = UITextField.new; | ||
textField.attributedText = [[NSAttributedString alloc] initWithString:@"Hello, world!"]; | ||
textField.bonChainable = BONChain.new.font([UIFont systemFontOfSize:16]); | ||
|
||
XCTAssertNotNil(textField.bonChainable); | ||
XCTAssertEqualObjects(textField.attributedText.string, @"Hello, world!"); | ||
|
||
NSMutableDictionary *controlAttributes = [self defaultAttributesForClass:[UITextField class] withString:@"Hello, world!"]; | ||
[controlAttributes[BONValueFromRange(0, 13)] addEntriesFromDictionary:@{ | ||
NSFontAttributeName : [UIFont systemFontOfSize:16], | ||
}]; | ||
|
||
BONAssertAttributedStringHasAttributes(textField.attributedText, controlAttributes); | ||
} | ||
|
||
#pragma mark - Helpers | ||
|
||
- (NSMutableDictionary *)defaultAttributesForClass:(Class)viewClass withString:(NSString *)string | ||
{ | ||
NSMutableDictionary *attributes = [NSMutableDictionary dictionary]; | ||
|
||
id view = [[viewClass alloc] init]; | ||
if ([view respondsToSelector:@selector(setAttributedText:)] && | ||
[view respondsToSelector:@selector(attributedText)]) { | ||
[view setAttributedText:[[NSAttributedString alloc] initWithString:string]]; | ||
[[view attributedText] enumerateAttributesInRange:NSMakeRange(0, string.length) options:0 usingBlock:^(NSDictionary<NSString *, id> *_Nonnull attrs, NSRange range, BOOL *_Nonnull stop) { | ||
attributes[[NSValue valueWithRange:range]] = [attrs mutableCopy]; | ||
}]; | ||
} | ||
|
||
return attributes; | ||
} | ||
|
||
@end |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// | ||
// UILabel+BonMotUtilities.h | ||
// Pods | ||
// | ||
// Created by Nora Trapp on 3/2/16. | ||
// | ||
// | ||
|
||
@import UIKit; | ||
@protocol BONChainable; | ||
|
||
@interface UILabel (BonMotUtilities) | ||
|
||
/** | ||
* Assign a @p BONChainable object to apply to the label text. When a new value is assigned to @p text the chain attributes will be applied. | ||
* If a new value is assigned directly to @p attributedText the @p bonChainable property will be set to @p nil. | ||
*/ | ||
@property (copy, nonatomic) id<BONChainable> bonChainable; | ||
|
||
@end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// | ||
// UILabel+BonMotUtilities.m | ||
// Pods | ||
// | ||
// Created by Nora Trapp on 3/2/16. | ||
// | ||
// | ||
|
||
#import "BonMot.h" | ||
@import ObjectiveC.runtime; | ||
|
||
@implementation UILabel (BonMotUtilities) | ||
|
||
- (void)setBonChainable:(id<BONChainable>)chainable | ||
{ | ||
objc_setAssociatedObject(self, @selector(bonChainable), chainable, OBJC_ASSOCIATION_COPY_NONATOMIC); | ||
|
||
if (chainable) { | ||
chainable.text.string = self.text; | ||
[self bon_setAttributedText:chainable.text.attributedString]; | ||
|
||
if (chainable.text.font) { | ||
self.font = chainable.text.font; | ||
} | ||
|
||
if (chainable.text.textColor) { | ||
self.textColor = chainable.text.textColor; | ||
} | ||
} | ||
} | ||
|
||
- (BONChain *)bonChainable | ||
{ | ||
return objc_getAssociatedObject(self, @selector(bonChainable)); | ||
} | ||
|
||
+ (void)load | ||
{ | ||
static dispatch_once_t once_token; | ||
dispatch_once(&once_token, ^{ | ||
Method originalSetTextMethod = class_getInstanceMethod(self, @selector(setText:)); | ||
Method newSetTextMethod = class_getInstanceMethod(self, @selector(bon_setText:)); | ||
method_exchangeImplementations(originalSetTextMethod, newSetTextMethod); | ||
|
||
Method originalSetAttributedTextMethod = class_getInstanceMethod(self, @selector(setAttributedText:)); | ||
Method newSetAttributedTextMethod = class_getInstanceMethod(self, @selector(bon_setAttributedText:)); | ||
method_exchangeImplementations(originalSetAttributedTextMethod, newSetAttributedTextMethod); | ||
}); | ||
} | ||
|
||
- (void)bon_setText:(NSString *)text | ||
{ | ||
if (self.bonChainable) { | ||
self.bonChainable.text.string = text; | ||
[self bon_setAttributedText:self.bonChainable.text.attributedString]; | ||
} | ||
else { | ||
[self bon_setText:text]; | ||
} | ||
} | ||
|
||
- (void)bon_setAttributedText:(NSAttributedString *)attributedText | ||
{ | ||
if ([self.bonChainable.text.font isEqual:self.font]) { | ||
self.font = nil; | ||
} | ||
|
||
if ([self.bonChainable.text.textColor isEqual:self.textColor]) { | ||
self.textColor = nil; | ||
} | ||
|
||
self.bonChainable = nil; | ||
[self bon_setAttributedText:attributedText]; | ||
} | ||
|
||
@end |
Oops, something went wrong.