diff --git a/AttributedLabel Example/AttributedLabel Example.xcodeproj/project.xcworkspace/xcshareddata/AttributedLabel Example.xccheckout b/AttributedLabel Example/AttributedLabel Example.xcodeproj/project.xcworkspace/xcshareddata/AttributedLabel Example.xccheckout new file mode 100644 index 0000000..1c3dadd --- /dev/null +++ b/AttributedLabel Example/AttributedLabel Example.xcodeproj/project.xcworkspace/xcshareddata/AttributedLabel Example.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 8E00B687-E064-4809-8B28-8796809624B8 + IDESourceControlProjectName + AttributedLabel Example + IDESourceControlProjectOriginsDictionary + + C1454787-2CDA-4B38-A9B3-B2369AB9C48B + https://github.com/JonasGessner/OHAttributedLabel.git + + IDESourceControlProjectPath + AttributedLabel Example/AttributedLabel Example.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + C1454787-2CDA-4B38-A9B3-B2369AB9C48B + ../../.. + + IDESourceControlProjectURL + https://github.com/JonasGessner/OHAttributedLabel.git + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + C1454787-2CDA-4B38-A9B3-B2369AB9C48B + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + C1454787-2CDA-4B38-A9B3-B2369AB9C48B + IDESourceControlWCCName + OHAttributedLabel + + + + diff --git a/AttributedLabel Example/AttributedLabel Example.xcworkspace/xcshareddata/AttributedLabel Example.xccheckout b/AttributedLabel Example/AttributedLabel Example.xcworkspace/xcshareddata/AttributedLabel Example.xccheckout new file mode 100644 index 0000000..f033151 --- /dev/null +++ b/AttributedLabel Example/AttributedLabel Example.xcworkspace/xcshareddata/AttributedLabel Example.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 183D72E1-D028-4B77-8A12-AC9BBB43440E + IDESourceControlProjectName + AttributedLabel Example + IDESourceControlProjectOriginsDictionary + + C1454787-2CDA-4B38-A9B3-B2369AB9C48B + https://github.com/JonasGessner/OHAttributedLabel.git + + IDESourceControlProjectPath + AttributedLabel Example/AttributedLabel Example.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + C1454787-2CDA-4B38-A9B3-B2369AB9C48B + ../.. + + IDESourceControlProjectURL + https://github.com/JonasGessner/OHAttributedLabel.git + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + C1454787-2CDA-4B38-A9B3-B2369AB9C48B + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + C1454787-2CDA-4B38-A9B3-B2369AB9C48B + IDESourceControlWCCName + OHAttributedLabel + + + + diff --git a/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.m b/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.m index f6962dd..a1b5cca 100644 --- a/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.m +++ b/AttributedLabel Example/Classes/BasicDemo/BasicDemoViewController.m @@ -175,6 +175,10 @@ -(UIColor*)attributedLabel:(OHAttributedLabel*)attrLabel colorForLink:(NSTextChe } } +- (void)attributedLabel:(OHAttributedLabel *)attributedLabel longPressedLink:(NSTextCheckingResult *)linkInfo { + NSLog(@"Long Pressed Link %@", linkInfo); +} + -(BOOL)attributedLabel:(OHAttributedLabel *)attributedLabel shouldFollowLink:(NSTextCheckingResult *)linkInfo { [self.visitedLinks addObject:objectForLinkInfo(linkInfo)]; diff --git a/AttributedLabel Example/Classes/CustomLinksDemo/CustomLinksViewController.m b/AttributedLabel Example/Classes/CustomLinksDemo/CustomLinksViewController.m index 0e896a9..ddebe67 100644 --- a/AttributedLabel Example/Classes/CustomLinksDemo/CustomLinksViewController.m +++ b/AttributedLabel Example/Classes/CustomLinksDemo/CustomLinksViewController.m @@ -178,6 +178,9 @@ -(IBAction)changeLineSpacing:(UISlider*)slider #pragma mark - OHAttributedString Delegate Method ///////////////////////////////////////////////////////////////////////////// +- (void)attributedLabel:(OHAttributedLabel *)attributedLabel longPressedLink:(NSTextCheckingResult *)linkInfo { + NSLog(@"Long Pressed Link %@", linkInfo); +} -(BOOL)attributedLabel:(OHAttributedLabel *)attributedLabel shouldFollowLink:(NSTextCheckingResult *)linkInfo { diff --git a/AttributedLabel Example/Classes/TableViewDemo/TableViewDemoViewController.m b/AttributedLabel Example/Classes/TableViewDemo/TableViewDemoViewController.m index 3742d5f..ee4827c 100644 --- a/AttributedLabel Example/Classes/TableViewDemo/TableViewDemoViewController.m +++ b/AttributedLabel Example/Classes/TableViewDemo/TableViewDemoViewController.m @@ -141,6 +141,10 @@ -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath * #pragma mark - OHAttributedLabel Delegate Method ///////////////////////////////////////////////////////////////////////////// +- (void)attributedLabel:(OHAttributedLabel *)attributedLabel longPressedLink:(NSTextCheckingResult *)linkInfo { + NSLog(@"Long Pressed Link %@", linkInfo); +} + -(BOOL)attributedLabel:(OHAttributedLabel *)attributedLabel shouldFollowLink:(NSTextCheckingResult *)linkInfo { if ([[UIApplication sharedApplication] canOpenURL:linkInfo.extendedURL]) diff --git a/OHAttributedLabel/Source/NSAttributedString+Attributes.m b/OHAttributedLabel/Source/NSAttributedString+Attributes.m index e64f962..6f0be76 100644 --- a/OHAttributedLabel/Source/NSAttributedString+Attributes.m +++ b/OHAttributedLabel/Source/NSAttributedString+Attributes.m @@ -73,7 +73,7 @@ -(CGSize)sizeConstrainedToSize:(CGSize)maxSize fitRange:(NSRange*)fitRange sz = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,CFRangeMake(0,0),NULL,maxSize,&fitCFRange); sz = CGSizeMake( floorf(sz.width+1) , floorf(sz.height+1) ); // take 1pt of margin for security CFRelease(framesetter); - + if (fitRange) { *fitRange = NSMakeRange((NSUInteger)fitCFRange.location, (NSUInteger)fitCFRange.length); @@ -194,7 +194,7 @@ -(void)setFontFamily:(NSString*)fontFamily size:(CGFloat)size bold:(BOOL)isBold CTFontRef aFont = CTFontCreateWithFontDescriptor(desc, size, NULL); CFRelease(desc); if (!aFont) return; - + [self removeAttribute:(__bridge NSString*)kCTFontAttributeName range:range]; // Work around for Apple leak [self addAttribute:(__bridge NSString*)kCTFontAttributeName value:(__bridge id)aFont range:range]; CFRelease(aFont); @@ -236,11 +236,15 @@ -(void)changeFontWithTraits:(CTFontSymbolicTraits)traits [self beginEditing]; do { // Get font at startPoint + BOOL hadCurrentFont = YES; + CTFontRef currentFont = (__bridge CTFontRef)[self attribute:(__bridge NSString*)kCTFontAttributeName atIndex:startPoint effectiveRange:&effectiveRange]; - if (!currentFont) - { + + if (!currentFont) { + hadCurrentFont = NO; currentFont = CTFontCreateUIFontForLanguage(kCTFontLabelFontType, 0.0, NULL); } + // The range for which this font is effective NSRange fontRange = NSIntersectionRange(range, effectiveRange); // Create the font variant for this font according to new traits @@ -272,9 +276,12 @@ -(void)changeFontWithTraits:(CTFontSymbolicTraits)traits if (fontNameRef) CFRelease(fontNameRef); } + if (!hadCurrentFont) { + CFRelease(currentFont); + } + // Apply the new font with new traits - if (newFont) - { + if (newFont) { [self removeAttribute:(__bridge NSString*)kCTFontAttributeName range:fontRange]; // Work around for Apple leak [self addAttribute:(__bridge NSString*)kCTFontAttributeName value:(__bridge id)newFont range:fontRange]; CFRelease(newFont); @@ -296,18 +303,18 @@ -(void)setTextBold:(BOOL)isBold range:(NSRange)range [self changeFontWithTraits:(isBold?kCTFontTraitBold:0) mask:kCTFontTraitBold range:range newFontFinder:^NSString *(NSString *currentFontName) - { - if ([currentFontName isEqualToString:kHelveticaNeueUI_Italic] || [currentFontName isEqualToString:kHelveticaNeueUI_Bold_Italic]) - { - // Italic private font - return isBold ? kHelveticaNeueUI_Bold_Italic : kHelveticaNeueUI_Italic; - } else if ([currentFontName isEqualToString:kHelveticaNeueUI] || [currentFontName isEqualToString:kHelveticaNeueUI_Bold]) { - // Non-Italic private font - return isBold ? kHelveticaNeueUI_Bold : kHelveticaNeueUI; - } else { - return nil; - } - }]; + { + if ([currentFontName isEqualToString:kHelveticaNeueUI_Italic] || [currentFontName isEqualToString:kHelveticaNeueUI_Bold_Italic]) + { + // Italic private font + return isBold ? kHelveticaNeueUI_Bold_Italic : kHelveticaNeueUI_Italic; + } else if ([currentFontName isEqualToString:kHelveticaNeueUI] || [currentFontName isEqualToString:kHelveticaNeueUI_Bold]) { + // Non-Italic private font + return isBold ? kHelveticaNeueUI_Bold : kHelveticaNeueUI; + } else { + return nil; + } + }]; } -(void)setTextItalics:(BOOL)isItalics range:(NSRange)range @@ -366,9 +373,9 @@ -(void)modifyParagraphStylesInRange:(NSRange)range withBlock:(void(^)(OHParagrap while (NSLocationInRange(loc, range)) { CTParagraphStyleRef currentCTStyle = (__bridge CTParagraphStyleRef)[self attribute:(__bridge NSString*)kCTParagraphStyleAttributeName - atIndex:loc longestEffectiveRange:rangePtr inRange:range]; + atIndex:loc longestEffectiveRange:rangePtr inRange:range]; __block OHParagraphStyle* paraStyle = [OHParagraphStyle paragraphStyleWithCTParagraphStyle:currentCTStyle]; - block(paraStyle); + block(paraStyle); [self setParagraphStyle:paraStyle range:*rangePtr]; loc = NSMaxRange(*rangePtr); diff --git a/OHAttributedLabel/Source/OHAttributedLabel.h b/OHAttributedLabel/Source/OHAttributedLabel.h index 7d43241..f16a3e7 100755 --- a/OHAttributedLabel/Source/OHAttributedLabel.h +++ b/OHAttributedLabel/Source/OHAttributedLabel.h @@ -39,6 +39,9 @@ @protocol OHAttributedLabelDelegate @optional -(BOOL)attributedLabel:(OHAttributedLabel*)attributedLabel shouldFollowLink:(NSTextCheckingResult*)linkInfo; + +-(void)attributedLabel:(OHAttributedLabel*)attributedLabel longPressedLink:(NSTextCheckingResult*)linkInfo; + //! @parameter underlineStyle Combination of CTUnderlineStyle and CTUnderlineStyleModifiers -(UIColor*)attributedLabel:(OHAttributedLabel*)attributedLabel colorForLink:(NSTextCheckingResult*)linkInfo underlineStyle:(int32_t*)underlineStyle; @end diff --git a/OHAttributedLabel/Source/OHAttributedLabel.m b/OHAttributedLabel/Source/OHAttributedLabel.m index 7053881..ee65ebe 100755 --- a/OHAttributedLabel/Source/OHAttributedLabel.m +++ b/OHAttributedLabel/Source/OHAttributedLabel.m @@ -60,6 +60,7 @@ @interface OHAttributedLabel(/* Private */) NSMutableArray* _customLinks; CGPoint _touchStartPoint; UIGestureRecognizer *_gestureRecogniser; + UIGestureRecognizer *_longTapGestureReconizer; } @property(nonatomic, retain) NSTextCheckingResult* activeLink; -(NSTextCheckingResult*)linkAtCharacterIndex:(CFIndex)idx; @@ -146,6 +147,10 @@ - (void)commonInit _gestureRecogniser = [[OHTouchesGestureRecognizer alloc] initWithTarget:self action:@selector(_gestureRecognised:)]; _gestureRecogniser.delegate = self; [self addGestureRecognizer:_gestureRecogniser]; + + _longTapGestureReconizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)]; + _longTapGestureReconizer.delegate = self; + [self addGestureRecognizer:_longTapGestureReconizer]; } - (id) initWithFrame:(CGRect)aFrame @@ -442,6 +447,23 @@ -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event return hitResult; } +- (void)longPress:(UILongPressGestureRecognizer *)gesture { + CGPoint pt = [gesture locationInView:self]; + + if (gesture.state == UIGestureRecognizerStateBegan) { + // Check that the link on touchEnd is the same as the link on touchBegan + NSTextCheckingResult* linkAtTouchesEnded = [self linkAtPoint:pt]; + BOOL closeToStart = (fabs(_touchStartPoint.x - pt.x) < 10 && fabs(_touchStartPoint.y - pt.y) < 10); + + // we must check on equality of the ranges themselves since the data detectors create new results + if (_activeLink && (NSEqualRanges(_activeLink.range,linkAtTouchesEnded.range) || closeToStart)) { + // Same link on touchEnded than the one on touchBegan, so trigger it + [self processLongPressActiveLink]; + } + } + +} + -(void)_gestureRecognised:(UIGestureRecognizer*)recogniser { CGPoint pt = [recogniser locationInView:self]; @@ -491,6 +513,14 @@ -(void)_gestureRecognised:(UIGestureRecognizer*)recogniser } } +- (void)processLongPressActiveLink { + NSTextCheckingResult* linkToOpen = _activeLink; + + if ([self.delegate respondsToSelector:@selector(attributedLabel:longPressedLink:)]) { + [self.delegate attributedLabel:self longPressedLink:linkToOpen]; + } +} + - (void)processActiveLink { NSTextCheckingResult* linkToOpen = _activeLink; @@ -677,7 +707,7 @@ - (CGSize)sizeThatFits:(CGSize)size ///////////////////////////////////////////////////////////////////////////////////// - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { - return ([[otherGestureRecognizer.view class] isSubclassOfClass:[UIScrollView class]]); + return (otherGestureRecognizer == _longTapGestureReconizer || otherGestureRecognizer == _gestureRecogniser || [[otherGestureRecognizer.view class] isSubclassOfClass:[UIScrollView class]]); }