diff --git a/KILabel/Source/KILabel.h b/KILabel/Source/KILabel.h index 74c6cc6..26ec765 100644 --- a/KILabel/Source/KILabel.h +++ b/KILabel/Source/KILabel.h @@ -176,6 +176,12 @@ IB_DESIGNABLE */ @property (nullable, nonatomic, copy) KILinkTapHandler urlLinkTapHandler; + +/** + * Callback block for KILinkTypePlainText link tap. + */ +@property (nullable, nonatomic, copy) KILinkTapHandler planTextHandler; + /** ****************************************************************************************** ** * @name Geometry ** ****************************************************************************************** **/ diff --git a/KILabel/Source/KILabel.m b/KILabel/Source/KILabel.m index 37dbbff..548eba6 100644 --- a/KILabel/Source/KILabel.m +++ b/KILabel/Source/KILabel.m @@ -55,15 +55,13 @@ @interface KILabel() #pragma mark - Implementation -@implementation KILabel -{ +@implementation KILabel { NSMutableDictionary *_linkTypeAttributes; } #pragma mark - Construction -- (id)initWithFrame:(CGRect)frame -{ +- (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { @@ -73,8 +71,7 @@ - (id)initWithFrame:(CGRect)frame return self; } -- (id)initWithCoder:(NSCoder *)aDecoder -{ +- (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { @@ -85,8 +82,7 @@ - (id)initWithCoder:(NSCoder *)aDecoder } // Common initialisation. Must be done once during construction. -- (void)setupTextSystem -{ +- (void)setupTextSystem { // Create a text container and set it up to match our label properties _textContainer = [[NSTextContainer alloc] init]; _textContainer.lineFragmentPadding = 0; @@ -127,24 +123,21 @@ - (void)setupTextSystem #pragma mark - Text and Style management -- (void)setAutomaticLinkDetectionEnabled:(BOOL)decorating -{ +- (void)setAutomaticLinkDetectionEnabled:(BOOL)decorating { _automaticLinkDetectionEnabled = decorating; // Make sure the text is updated properly [self updateTextStoreWithText]; } -- (void)setLinkDetectionTypes:(KILinkTypeOption)linkDetectionTypes -{ +- (void)setLinkDetectionTypes:(KILinkTypeOption)linkDetectionTypes { _linkDetectionTypes = linkDetectionTypes; // Make sure the text is updated properly [self updateTextStoreWithText]; } -- (NSDictionary *)linkAtPoint:(CGPoint)location -{ +- (NSDictionary *)linkAtPoint:(CGPoint)location { // Do nothing if we have no text if (_textStorage.string.length == 0) { @@ -168,12 +161,10 @@ - (NSDictionary *)linkAtPoint:(CGPoint)location return nil; // Find the word that was touched and call the detection block - for (NSDictionary *dictionary in self.linkRanges) - { + for (NSDictionary *dictionary in self.linkRanges) { NSRange range = [[dictionary objectForKey:KILabelRangeKey] rangeValue]; - if ((touchedChar >= range.location) && touchedChar < (range.location + range.length)) - { + if ((touchedChar >= range.location) && touchedChar < (range.location + range.length)) { return dictionary; } } @@ -182,17 +173,14 @@ - (NSDictionary *)linkAtPoint:(CGPoint)location } // Applies background color to selected range. Used to hilight touched links -- (void)setSelectedRange:(NSRange)range -{ +- (void)setSelectedRange:(NSRange)range { // Remove the current selection if the selection is changing - if (self.selectedRange.length && !NSEqualRanges(self.selectedRange, range)) - { + if (self.selectedRange.length && !NSEqualRanges(self.selectedRange, range)) { [_textStorage removeAttribute:NSBackgroundColorAttributeName range:self.selectedRange]; } // Apply the new selection to the text - if (range.length && _selectedLinkBackgroundColor != nil) - { + if (range.length && _selectedLinkBackgroundColor != nil) { [_textStorage addAttribute:NSBackgroundColorAttributeName value:_selectedLinkBackgroundColor range:range]; } @@ -202,22 +190,19 @@ - (void)setSelectedRange:(NSRange)range [self setNeedsDisplay]; } -- (void)setNumberOfLines:(NSInteger)numberOfLines -{ +- (void)setNumberOfLines:(NSInteger)numberOfLines { [super setNumberOfLines:numberOfLines]; _textContainer.maximumNumberOfLines = numberOfLines; } -- (void)setText:(NSString *)text -{ +- (void)setText:(NSString *)text { // Pass the text to the super class first [super setText:text]; // Update our text store with an attributed string based on the original // label text properties. - if (!text) - { + if (!text) { text = @""; } @@ -225,24 +210,21 @@ - (void)setText:(NSString *)text [self updateTextStoreWithAttributedString:attributedText]; } -- (void)setAttributedText:(NSAttributedString *)attributedText -{ +- (void)setAttributedText:(NSAttributedString *)attributedText { // Pass the text to the super class first [super setAttributedText:attributedText]; [self updateTextStoreWithAttributedString:attributedText]; } -- (void)setSystemURLStyle:(BOOL)systemURLStyle -{ +- (void)setSystemURLStyle:(BOOL)systemURLStyle { _systemURLStyle = systemURLStyle; // Force refresh self.text = self.text; } -- (NSDictionary*)attributesForLinkType:(KILinkType)linkType -{ +- (NSDictionary*)attributesForLinkType:(KILinkType)linkType { NSDictionary *attributes = _linkTypeAttributes[@(linkType)]; if (!attributes) @@ -253,14 +235,10 @@ - (NSDictionary*)attributesForLinkType:(KILinkType)linkType return attributes; } -- (void)setAttributes:(NSDictionary*)attributes forLinkType:(KILinkType)linkType -{ - if (attributes) - { +- (void)setAttributes:(NSDictionary*)attributes forLinkType:(KILinkType)linkType { + if (attributes) { _linkTypeAttributes[@(linkType)] = attributes; - } - else - { + } else { [_linkTypeAttributes removeObjectForKey:@(linkType)]; } @@ -270,49 +248,35 @@ - (void)setAttributes:(NSDictionary*)attributes forLinkType:(KILinkType)linkType #pragma mark - Text Storage Management -- (void)updateTextStoreWithText -{ +- (void)updateTextStoreWithText { // Now update our storage from either the attributedString or the plain text - if (self.attributedText) - { + if (self.attributedText) { [self updateTextStoreWithAttributedString:self.attributedText]; - } - else if (self.text) - { + } else if (self.text) { [self updateTextStoreWithAttributedString:[[NSAttributedString alloc] initWithString:self.text attributes:[self attributesFromProperties]]]; - } - else - { + } else { [self updateTextStoreWithAttributedString:[[NSAttributedString alloc] initWithString:@"" attributes:[self attributesFromProperties]]]; } [self setNeedsDisplay]; } -- (void)updateTextStoreWithAttributedString:(NSAttributedString *)attributedString -{ - if (attributedString.length != 0) - { +- (void)updateTextStoreWithAttributedString:(NSAttributedString *)attributedString { + if (attributedString.length != 0) { attributedString = [KILabel sanitizeAttributedString:attributedString]; } - if (self.isAutomaticLinkDetectionEnabled && (attributedString.length != 0)) - { + if (self.isAutomaticLinkDetectionEnabled && (attributedString.length != 0)) { self.linkRanges = [self getRangesForLinks:attributedString]; attributedString = [self addLinkAttributesToAttributedString:attributedString linkRanges:self.linkRanges]; - } - else - { + } else { self.linkRanges = nil; } - if (_textStorage) - { + if (_textStorage) { // Set the string on the storage [_textStorage setAttributedString:attributedString]; - } - else - { + } else { // Create a new text storage and attach it correctly to the layout manager _textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString]; [_textStorage addLayoutManager:_layoutManager]; @@ -322,29 +286,22 @@ - (void)updateTextStoreWithAttributedString:(NSAttributedString *)attributedStri // Returns attributed string attributes based on the text properties set on the label. // These are styles that are only applied when NOT using the attributedText directly. -- (NSDictionary *)attributesFromProperties -{ +- (NSDictionary *)attributesFromProperties { // Setup shadow attributes NSShadow *shadow = shadow = [[NSShadow alloc] init]; - if (self.shadowColor) - { + if (self.shadowColor) { shadow.shadowColor = self.shadowColor; shadow.shadowOffset = self.shadowOffset; - } - else - { + } else { shadow.shadowOffset = CGSizeMake(0, -1); shadow.shadowColor = nil; } // Setup color attributes UIColor *color = self.textColor; - if (!self.isEnabled) - { + if (!self.isEnabled) { color = [UIColor lightGrayColor]; - } - else if (self.isHighlighted) - { + } else if (self.isHighlighted) { color = self.highlightedTextColor; } @@ -352,13 +309,12 @@ - (NSDictionary *)attributesFromProperties NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init]; paragraph.alignment = self.textAlignment; - // Create the dictionary - NSDictionary *attributes = @{NSFontAttributeName : self.font, - NSForegroundColorAttributeName : color, - NSShadowAttributeName : shadow, - NSParagraphStyleAttributeName : paragraph, - }; - return attributes; + // Return the dictionary + return @{NSFontAttributeName : self.font, + NSForegroundColorAttributeName : color, + NSShadowAttributeName : shadow, + NSParagraphStyleAttributeName : paragraph, + }; } /** @@ -369,30 +325,25 @@ - (NSDictionary *)attributesFromProperties * * @return Array of dictionaries describing the links. */ -- (NSArray *)getRangesForLinks:(NSAttributedString *)text -{ +- (NSArray *)getRangesForLinks:(NSAttributedString *)text { NSMutableArray *rangesForLinks = [[NSMutableArray alloc] init]; - if (self.linkDetectionTypes & KILinkTypeOptionUserHandle) - { + if (self.linkDetectionTypes & KILinkTypeOptionUserHandle) { [rangesForLinks addObjectsFromArray:[self getRangesForUserHandles:text.string]]; } - if (self.linkDetectionTypes & KILinkTypeOptionHashtag) - { + if (self.linkDetectionTypes & KILinkTypeOptionHashtag) { [rangesForLinks addObjectsFromArray:[self getRangesForHashtags:text.string]]; } - if (self.linkDetectionTypes & KILinkTypeOptionURL) - { + if (self.linkDetectionTypes & KILinkTypeOptionURL) { [rangesForLinks addObjectsFromArray:[self getRangesForURLs:self.attributedText]]; } return rangesForLinks; } -- (NSArray *)getRangesForUserHandles:(NSString *)text -{ +- (NSArray *)getRangesForUserHandles:(NSString *)text { NSMutableArray *rangesForUserHandles = [[NSMutableArray alloc] init]; // Setup a regular expression for user handles and hashtags @@ -407,13 +358,11 @@ - (NSArray *)getRangesForUserHandles:(NSString *)text NSArray *matches = [regex matchesInString:text options:0 range:NSMakeRange(0, text.length)]; // Add all our ranges to the result - for (NSTextCheckingResult *match in matches) - { + for (NSTextCheckingResult *match in matches) { NSRange matchRange = [match range]; NSString *matchString = [text substringWithRange:matchRange]; - if (![self ignoreMatch:matchString]) - { + if (![self ignoreMatch:matchString]) { [rangesForUserHandles addObject:@{KILabelLinkTypeKey : @(KILinkTypeUserHandle), KILabelRangeKey : [NSValue valueWithRange:matchRange], KILabelLinkKey : matchString @@ -424,8 +373,7 @@ - (NSArray *)getRangesForUserHandles:(NSString *)text return rangesForUserHandles; } -- (NSArray *)getRangesForHashtags:(NSString *)text -{ +- (NSArray *)getRangesForHashtags:(NSString *)text { NSMutableArray *rangesForHashtags = [[NSMutableArray alloc] init]; // Setup a regular expression for user handles and hashtags @@ -440,13 +388,11 @@ - (NSArray *)getRangesForHashtags:(NSString *)text NSArray *matches = [regex matchesInString:text options:0 range:NSMakeRange(0, text.length)]; // Add all our ranges to the result - for (NSTextCheckingResult *match in matches) - { + for (NSTextCheckingResult *match in matches) { NSRange matchRange = [match range]; NSString *matchString = [text substringWithRange:matchRange]; - if (![self ignoreMatch:matchString]) - { + if (![self ignoreMatch:matchString]) { [rangesForHashtags addObject:@{KILabelLinkTypeKey : @(KILinkTypeHashtag), KILabelRangeKey : [NSValue valueWithRange:matchRange], KILabelLinkKey : matchString, @@ -458,8 +404,7 @@ - (NSArray *)getRangesForHashtags:(NSString *)text } -- (NSArray *)getRangesForURLs:(NSAttributedString *)text -{ +- (NSArray *)getRangesForURLs:(NSAttributedString *)text { NSMutableArray *rangesForURLs = [[NSMutableArray alloc] init];; // Use a data detector to find urls in the text @@ -473,8 +418,7 @@ - (NSArray *)getRangesForURLs:(NSAttributedString *)text range:NSMakeRange(0, text.length)]; // Add a range entry for every url we found - for (NSTextCheckingResult *match in matches) - { + for (NSTextCheckingResult *match in matches) { NSRange matchRange = [match range]; // If there's a link embedded in the attributes, use that instead of the raw text @@ -482,10 +426,8 @@ - (NSArray *)getRangesForURLs:(NSAttributedString *)text if (realURL == nil) realURL = [plainText substringWithRange:matchRange]; - if (![self ignoreMatch:realURL]) - { - if ([match resultType] == NSTextCheckingTypeLink) - { + if (![self ignoreMatch:realURL]) { + if ([match resultType] == NSTextCheckingTypeLink) { [rangesForURLs addObject:@{KILabelLinkTypeKey : @(KILinkTypeURL), KILabelRangeKey : [NSValue valueWithRange:matchRange], KILabelLinkKey : realURL, @@ -497,17 +439,15 @@ - (NSArray *)getRangesForURLs:(NSAttributedString *)text return rangesForURLs; } -- (BOOL)ignoreMatch:(NSString*)string -{ +- (BOOL)ignoreMatch:(NSString*)string { return [_ignoredKeywords containsObject:[string lowercaseString]]; } -- (NSAttributedString *)addLinkAttributesToAttributedString:(NSAttributedString *)string linkRanges:(NSArray *)linkRanges -{ +- (NSAttributedString *)addLinkAttributesToAttributedString:(NSAttributedString *)string + linkRanges:(NSArray *)linkRanges { NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:string]; - for (NSDictionary *dictionary in linkRanges) - { + for (NSDictionary *dictionary in linkRanges) { NSRange range = [[dictionary objectForKey:KILabelRangeKey] rangeValue]; KILinkType linkType = [dictionary[KILabelLinkTypeKey] unsignedIntegerValue]; @@ -517,8 +457,7 @@ - (NSAttributedString *)addLinkAttributesToAttributedString:(NSAttributedString [attributedString addAttributes:attributes range:range]; // Add an URL attribute if this is a URL - if (_systemURLStyle && ((KILinkType)[dictionary[KILabelLinkTypeKey] unsignedIntegerValue] == KILinkTypeURL)) - { + if (_systemURLStyle && ((KILinkType)[dictionary[KILabelLinkTypeKey] unsignedIntegerValue] == KILinkTypeURL)) { // Add a link attribute using the stored link [attributedString addAttribute:NSLinkAttributeName value:dictionary[KILabelLinkKey] range:range]; } @@ -529,8 +468,7 @@ - (NSAttributedString *)addLinkAttributesToAttributedString:(NSAttributedString #pragma mark - Layout and Rendering -- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines -{ +- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines { // Use our text container to calculate the bounds required. First save our // current text container setup CGSize savedTextContainerSize = _textContainer.size; @@ -548,8 +486,7 @@ - (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)num textBounds.size.width = ceil(textBounds.size.width); textBounds.size.height = ceil(textBounds.size.height); - if (textBounds.size.height < bounds.size.height) - { + if (textBounds.size.height < bounds.size.height) { // Take verical alignment into account CGFloat offsetY = (bounds.size.height - textBounds.size.height) / 2.0; textBounds.origin.y += offsetY; @@ -562,8 +499,7 @@ - (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)num return textBounds; } -- (void)drawTextInRect:(CGRect)rect -{ +- (void)drawTextInRect:(CGRect)rect { // Don't call super implementation. Might want to uncomment this out when // debugging layout and rendering problems. // [super drawTextInRect:rect]; @@ -578,16 +514,14 @@ - (void)drawTextInRect:(CGRect)rect } // Returns the XY offset of the range of glyphs from the view's origin -- (CGPoint)calcGlyphsPositionInView -{ +- (CGPoint)calcGlyphsPositionInView { CGPoint textOffset = CGPointZero; CGRect textBounds = [_layoutManager usedRectForTextContainer:_textContainer]; textBounds.size.width = ceil(textBounds.size.width); textBounds.size.height = ceil(textBounds.size.height); - if (textBounds.size.height < self.bounds.size.height) - { + if (textBounds.size.height < self.bounds.size.height) { CGFloat paddingHeight = (self.bounds.size.height - textBounds.size.height) / 2.0; textOffset.y = paddingHeight; } @@ -595,30 +529,24 @@ - (CGPoint)calcGlyphsPositionInView return textOffset; } -- (void)setFrame:(CGRect)frame -{ +- (void)setFrame:(CGRect)frame { [super setFrame:frame]; - _textContainer.size = self.bounds.size; } -- (void)setBounds:(CGRect)bounds -{ +- (void)setBounds:(CGRect)bounds { [super setBounds:bounds]; - _textContainer.size = self.bounds.size; } -- (void)layoutSubviews -{ +- (void)layoutSubviews { [super layoutSubviews]; // Update our container size when the view frame changes _textContainer.size = self.bounds.size; } -- (void)setIgnoredKeywords:(NSSet *)ignoredKeywords -{ +- (void)setIgnoredKeywords:(NSSet *)ignoredKeywords { NSMutableSet *set = [NSMutableSet setWithCapacity:ignoredKeywords.count]; [ignoredKeywords enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { @@ -630,8 +558,7 @@ - (void)setIgnoredKeywords:(NSSet *)ignoredKeywords #pragma mark - Interactions -- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event -{ +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { _isTouchMoved = NO; // Get the info for the touched link if there is one @@ -639,32 +566,27 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event CGPoint touchLocation = [[touches anyObject] locationInView:self]; touchedLink = [self linkAtPoint:touchLocation]; - if (touchedLink) - { + if (touchedLink) { self.selectedRange = [[touchedLink objectForKey:KILabelRangeKey] rangeValue]; - } - else - { + } else { + if (_planTextHandler) { + _planTextHandler(self, self.text, NSMakeRange(0, self.text.length)); + } [super touchesBegan:touches withEvent:event]; } } -- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event -{ +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesMoved:touches withEvent:event]; - _isTouchMoved = YES; } -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event -{ +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesEnded:touches withEvent:event]; // If the user dragged their finger we ignore the touch - if (_isTouchMoved) - { + if (_isTouchMoved) { self.selectedRange = NSMakeRange(0, 0); - return; } @@ -673,51 +595,42 @@ - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event CGPoint touchLocation = [[touches anyObject] locationInView:self]; touchedLink = [self linkAtPoint:touchLocation]; - if (touchedLink) - { + if (touchedLink) { NSRange range = [[touchedLink objectForKey:KILabelRangeKey] rangeValue]; NSString *touchedSubstring = [touchedLink objectForKey:KILabelLinkKey]; KILinkType linkType = (KILinkType)[[touchedLink objectForKey:KILabelLinkTypeKey] intValue]; [self receivedActionForLinkType:linkType string:touchedSubstring range:range]; - } - else - { + } else { [super touchesBegan:touches withEvent:event]; } self.selectedRange = NSMakeRange(0, 0); } -- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event -{ +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesCancelled:touches withEvent:event]; // Make sure we don't leave a selection when the touch is cancelled self.selectedRange = NSMakeRange(0, 0); } -- (void)receivedActionForLinkType:(KILinkType)linkType string:(NSString*)string range:(NSRange)range -{ - switch (linkType) - { +- (void)receivedActionForLinkType:(KILinkType)linkType string:(NSString*)string range:(NSRange)range { + switch (linkType) { case KILinkTypeUserHandle: - if (_userHandleLinkTapHandler) - { + if (_userHandleLinkTapHandler) { _userHandleLinkTapHandler(self, string, range); } break; case KILinkTypeHashtag: - if (_hashtagLinkTapHandler) - { + if (_hashtagLinkTapHandler) { _hashtagLinkTapHandler(self, string, range); } break; case KILinkTypeURL: - if (_urlLinkTapHandler) - { + if (_urlLinkTapHandler) { _urlLinkTapHandler(self, string, range); } break; @@ -726,8 +639,7 @@ - (void)receivedActionForLinkType:(KILinkType)linkType string:(NSString*)string #pragma mark - Layout manager delegate --(BOOL)layoutManager:(NSLayoutManager *)layoutManager shouldBreakLineByWordBeforeCharacterAtIndex:(NSUInteger)charIndex -{ +-(BOOL)layoutManager:(NSLayoutManager *)layoutManager shouldBreakLineByWordBeforeCharacterAtIndex:(NSUInteger)charIndex{ // Don't allow line breaks inside URLs NSRange range; NSURL *linkURL = [layoutManager.textStorage attribute:NSLinkAttributeName atIndex:charIndex effectiveRange:&range]; @@ -735,8 +647,7 @@ -(BOOL)layoutManager:(NSLayoutManager *)layoutManager shouldBreakLineByWordBefor return !(linkURL && (charIndex > range.location) && (charIndex <= NSMaxRange(range))); } -+ (NSAttributedString *)sanitizeAttributedString:(NSAttributedString *)attributedString -{ ++ (NSAttributedString *)sanitizeAttributedString:(NSAttributedString *)attributedString { // Setup paragraph alignement properly. IB applies the line break style // to the attributed string. The problem is that the text container then // breaks at the first line of text. If we set the line break to wrapping @@ -748,8 +659,7 @@ + (NSAttributedString *)sanitizeAttributedString:(NSAttributedString *)attribute NSRange range; NSParagraphStyle *paragraphStyle = [attributedString attribute:NSParagraphStyleAttributeName atIndex:0 effectiveRange:&range]; - if (paragraphStyle == nil) - { + if (!paragraphStyle) { return attributedString; } diff --git a/KILabelDemo/KILabelDemo.xcodeproj/project.pbxproj b/KILabelDemo/KILabelDemo.xcodeproj/project.pbxproj index adb8754..a9c1b57 100644 --- a/KILabelDemo/KILabelDemo.xcodeproj/project.pbxproj +++ b/KILabelDemo/KILabelDemo.xcodeproj/project.pbxproj @@ -25,6 +25,8 @@ C97DB327183A59670028EA5C /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C97DB326183A59670028EA5C /* MessageUI.framework */; }; C9ABA08A1AEE5A8600363407 /* KILabelTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C9ABA0891AEE5A8600363407 /* KILabelTableViewController.m */; }; C9ABA08D1AEE5BAC00363407 /* KILabelTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = C9ABA08C1AEE5BAC00363407 /* KILabelTableViewCell.m */; }; + F21C4C4F1E1BACA500D2A802 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F21C4C4E1E1BACA500D2A802 /* Launch Screen.storyboard */; }; + F21C4C501E1BACA500D2A802 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F21C4C4E1E1BACA500D2A802 /* Launch Screen.storyboard */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -64,6 +66,7 @@ C9ABA0891AEE5A8600363407 /* KILabelTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KILabelTableViewController.m; sourceTree = ""; }; C9ABA08B1AEE5BAC00363407 /* KILabelTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KILabelTableViewCell.h; sourceTree = ""; }; C9ABA08C1AEE5BAC00363407 /* KILabelTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KILabelTableViewCell.m; sourceTree = ""; }; + F21C4C4E1E1BACA500D2A802 /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -94,6 +97,7 @@ C97DB2E1183A56EF0028EA5C = { isa = PBXGroup; children = ( + F21C4C4E1E1BACA500D2A802 /* Launch Screen.storyboard */, C97DB322183A57010028EA5C /* KILabel */, C97DB2F3183A56EF0028EA5C /* KILabelDemo */, C97DB312183A56F00028EA5C /* KILabelDemoTests */, @@ -224,7 +228,7 @@ isa = PBXProject; attributes = { CLASSPREFIX = KI; - LastUpgradeCheck = 0510; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Matthew Styles"; TargetAttributes = { C97DB30A183A56F00028EA5C = { @@ -258,6 +262,7 @@ files = ( C97DB306183A56EF0028EA5C /* Images.xcassets in Resources */, C97DB2F8183A56EF0028EA5C /* InfoPlist.strings in Resources */, + F21C4C4F1E1BACA500D2A802 /* Launch Screen.storyboard in Resources */, C97DB301183A56EF0028EA5C /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -266,6 +271,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + F21C4C501E1BACA500D2A802 /* Launch Screen.storyboard in Resources */, C97DB317183A56F00028EA5C /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -345,13 +351,19 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -383,13 +395,18 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -406,10 +423,10 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "KILabelDemo/KILabelDemo-Prefix.pch"; INFOPLIST_FILE = "KILabelDemo/KILabelDemo-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.compiledcreations.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; @@ -419,10 +436,10 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "KILabelDemo/KILabelDemo-Prefix.pch"; INFOPLIST_FILE = "KILabelDemo/KILabelDemo-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.compiledcreations.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; @@ -444,6 +461,7 @@ "$(inherited)", ); INFOPLIST_FILE = "KILabelDemoTests/KILabelDemoTests-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "MatthewStyles.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUNDLE_LOADER)"; WRAPPER_EXTENSION = xctest; @@ -462,6 +480,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "KILabelDemo/KILabelDemo-Prefix.pch"; INFOPLIST_FILE = "KILabelDemoTests/KILabelDemoTests-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "MatthewStyles.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUNDLE_LOADER)"; WRAPPER_EXTENSION = xctest; diff --git a/KILabelDemo/KILabelDemo/Images.xcassets/AppIcon.appiconset/Contents.json b/KILabelDemo/KILabelDemo/Images.xcassets/AppIcon.appiconset/Contents.json index a396706..b8236c6 100644 --- a/KILabelDemo/KILabelDemo/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/KILabelDemo/KILabelDemo/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,19 +1,44 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" } ], "info" : { diff --git a/KILabelDemo/KILabelDemo/Images.xcassets/Contents.json b/KILabelDemo/KILabelDemo/Images.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/KILabelDemo/KILabelDemo/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/KILabelDemo/KILabelDemo/Images.xcassets/LaunchImage.launchimage/Contents.json b/KILabelDemo/KILabelDemo/Images.xcassets/LaunchImage.launchimage/Contents.json deleted file mode 100644 index c79ebd3..0000000 --- a/KILabelDemo/KILabelDemo/Images.xcassets/LaunchImage.launchimage/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "orientation" : "portrait", - "idiom" : "iphone", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "subtype" : "retina4", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/KILabelDemo/KILabelDemo/KILabelDemo-Info.plist b/KILabelDemo/KILabelDemo/KILabelDemo-Info.plist index c667fa4..904a722 100644 --- a/KILabelDemo/KILabelDemo/KILabelDemo-Info.plist +++ b/KILabelDemo/KILabelDemo/KILabelDemo-Info.plist @@ -9,7 +9,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.compiledcreations.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -24,6 +24,8 @@ 1.0.0 LSRequiresIPhoneOS + UILaunchStoryboardName + Launch Screen UIMainStoryboardFile Main UIRequiredDeviceCapabilities diff --git a/KILabelDemo/KILabelDemo/KIViewController.m b/KILabelDemo/KILabelDemo/KIViewController.m index 908728f..69fde8b 100644 --- a/KILabelDemo/KILabelDemo/KIViewController.m +++ b/KILabelDemo/KILabelDemo/KIViewController.m @@ -76,6 +76,10 @@ - (void)viewDidLoad // Open URLs [self attemptOpenURL:[NSURL URLWithString:string]]; }; + + _label.planTextHandler = ^(KILabel *label, NSString *string, NSRange range) { + NSLog(@"no login "); + }; } #pragma mark - Action Targets @@ -263,4 +267,4 @@ -(void)mailComposeController:(MFMailComposeViewController *)controller didFinish [self dismissViewControllerAnimated:YES completion:NULL]; } -@end \ No newline at end of file +@end diff --git a/KILabelDemo/KILabelDemoTests/KILabelDemoTests-Info.plist b/KILabelDemo/KILabelDemoTests/KILabelDemoTests-Info.plist index 9bc8af7..169b6f7 100644 --- a/KILabelDemo/KILabelDemoTests/KILabelDemoTests-Info.plist +++ b/KILabelDemo/KILabelDemoTests/KILabelDemoTests-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - MatthewStyles.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/KILabelDemo/Launch Screen.storyboard b/KILabelDemo/Launch Screen.storyboard new file mode 100644 index 0000000..d85e669 --- /dev/null +++ b/KILabelDemo/Launch Screen.storyboard @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index 64b7b38..eda6ad4 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,11 @@ label.urlLinkTapHandler = ^(KILabel *label, NSString *string, NSRange range) { NSLog(@"URL tapped %@", string); }; +// Attach a block to be called when the user taps plan text area +label.planTextHandler = ^(KILabel *label, NSString *string, NSRange range) { +NSLog(@"Text tapped %@", string); +}; + [self.view addSubview:label]; ``` @@ -87,6 +92,11 @@ label.urlLinkTapHandler = { label, url, range in NSLog("URL \(url) tapped") } +// Attach a block to be called when the user taps plan text area +label.planTextHandler = { label, text, range in +NSLog("text \(text) tapped") +} + view.addSubview(label) ```