diff --git a/catalog/BasicInstantiation/BasicInstantiation/controllers/BasicInstantiationViewController.m b/catalog/BasicInstantiation/BasicInstantiation/controllers/BasicInstantiationViewController.m index f3bb262..7cddb74 100644 --- a/catalog/BasicInstantiation/BasicInstantiation/controllers/BasicInstantiationViewController.m +++ b/catalog/BasicInstantiation/BasicInstantiation/controllers/BasicInstantiationViewController.m @@ -85,10 +85,16 @@ - (void)viewDidLoad { #pragma mark - NIAttributedLabelDelegate -- (void)attributedLabel:(NIAttributedLabel *)attributedLabel didSelectTextCheckingResult:(NSTextCheckingResult *)result atPoint:(CGPoint)point { - if (result.resultType == NSTextCheckingTypeLink) { - [[UIApplication sharedApplication] openURL:result.URL]; - } +#ifdef IF_IOS8_OR_GREATER +- (BOOL)attributedLabel:(NIAttributedLabel *)attributedLabel shouldPresentAlertController:(UIAlertController *)alertController withTextCheckingResult:(NSTextCheckingResult *)result atPoint:(CGPoint)point{ + return true; } - +-(UIViewController*)attributedLabel:(NIAttributedLabel *)attributedLabel controllerToPresentAlertController:(UIAlertController *)alertController{ + return self; +} +#else +- (BOOL)attributedLabel:(NIAttributedLabel *)attributedLabel shouldPresentActionSheet:(UIActionSheet *)actionSheet withTextCheckingResult:(NSTextCheckingResult *)result atPoint:(CGPoint)point{ + return true; +} +#endif @end diff --git a/src/NIAttributedLabel.h b/src/NIAttributedLabel.h index 962d5cc..b2fefd8 100644 --- a/src/NIAttributedLabel.h +++ b/src/NIAttributedLabel.h @@ -129,6 +129,28 @@ extern NSString* const NIAttributedLabelLinkAttributeName; // Value is an NSText */ - (void)attributedLabel:(NIAttributedLabel *)attributedLabel didSelectTextCheckingResult:(NSTextCheckingResult *)result atPoint:(CGPoint)point; + +#ifdef IF_IOS8_OR_GREATER +/** + * Asks the receiver whether an alert controller should be displayed at the given point. + * + * If this method is not implemented by the receiver then @c alertController will always be displayed if it can. + * + * @c alertController will be populated with actions that match the data type that was selected. For + * example, a link will have the actions "Open in Safari" and "Copy URL". A phone number will have + * @"Call" and "Copy Phone Number". + * + * @param attributedLabel An attributed label asking the delegate whether to display the action + * sheet. + * @param alertController The alert controller that will be displayed if YES is returned. + * @param result The data detector result that was selected. + * @param point The point within @c attributedLabel where the result was tapped. + * @returns YES if @c alertController should be displayed. NO if @c alertController should not be + * displayed. + */ +- (BOOL)attributedLabel:(NIAttributedLabel *)attributedLabel shouldPresentAlertController:(UIAlertController *)alertController withTextCheckingResult:(NSTextCheckingResult *)result atPoint:(CGPoint)point; +-(UIViewController*)attributedLabel:(NIAttributedLabel *)attributedLabel controllerToPresentAlertController:(UIAlertController *)alertController; +#else /** * Asks the receiver whether an action sheet should be displayed at the given point. * @@ -147,6 +169,7 @@ extern NSString* const NIAttributedLabelLinkAttributeName; // Value is an NSText * displayed. */ - (BOOL)attributedLabel:(NIAttributedLabel *)attributedLabel shouldPresentActionSheet:(UIActionSheet *)actionSheet withTextCheckingResult:(NSTextCheckingResult *)result atPoint:(CGPoint)point; +#endif @end diff --git a/src/NIAttributedLabel.m b/src/NIAttributedLabel.m index cc915a5..0fd1d7c 100644 --- a/src/NIAttributedLabel.m +++ b/src/NIAttributedLabel.m @@ -111,7 +111,11 @@ - (CGSize)boxSize { @end +#ifdef IF_IOS8_OR_GREATER +@interface NIAttributedLabel() +#else @interface NIAttributedLabel() +#endif @property (nonatomic, strong) NSMutableAttributedString* mutableAttributedString; @@ -923,76 +927,178 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [self setNeedsDisplay]; } +#ifdef IF_IOS8_OR_GREATER +-(UIAlertController *)alertControllerForResult:(NSTextCheckingResult *)result { + UIAlertController *alertController = [[UIAlertController alloc] init]; + + NSString* title = nil; + if (NSTextCheckingTypeLink == result.resultType) { + if ([result.URL.scheme isEqualToString:@"mailto"]) { + title = result.URL.resourceSpecifier; + + UIAlertAction *mail = [UIAlertAction actionWithTitle:NSLocalizedString(@"Open in Mail", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [[UIApplication sharedApplication] openURL:self.actionSheetLink.URL]; + }]; + UIAlertAction *copy = [UIAlertAction actionWithTitle:NSLocalizedString(@"Copy Email Address", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [[UIPasteboard generalPasteboard] setString:self.actionSheetLink.URL.resourceSpecifier]; + }]; + + [alertController addAction:mail]; + [alertController addAction:copy]; + } else { + title = result.URL.absoluteString; + + UIAlertAction *link = [UIAlertAction actionWithTitle:NSLocalizedString(@"Open in Safari", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [[UIApplication sharedApplication] openURL:self.actionSheetLink.URL]; + }]; + UIAlertAction *copy = [UIAlertAction actionWithTitle:NSLocalizedString(@"Copy URL", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [[UIPasteboard generalPasteboard] setURL:self.actionSheetLink.URL]; + }]; + + [alertController addAction:link]; + [alertController addAction:copy]; + } + + } else if (NSTextCheckingTypePhoneNumber == result.resultType) { + title = result.phoneNumber; + + UIAlertAction *phone = [UIAlertAction actionWithTitle:NSLocalizedString(@"Call", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[@"tel:" stringByAppendingString:self.actionSheetLink.phoneNumber]]]; + }]; + UIAlertAction *copy = [UIAlertAction actionWithTitle:NSLocalizedString(@"Copy Phone Number", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [[UIPasteboard generalPasteboard] setString:self.actionSheetLink.phoneNumber]; + }]; + + [alertController addAction:phone]; + [alertController addAction:copy]; + + } else if (NSTextCheckingTypeAddress == result.resultType) { + title = [self.mutableAttributedString.string substringWithRange:self.actionSheetLink.range]; + + NSString* address = [self.mutableAttributedString.string substringWithRange:self.actionSheetLink.range]; + UIAlertAction *phone = [UIAlertAction actionWithTitle:NSLocalizedString(@"Open in Maps", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[[@"http://maps.google.com/maps?q=" stringByAppendingString:address] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]; + }]; + UIAlertAction *copy = [UIAlertAction actionWithTitle:NSLocalizedString(@"Copy Address", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [[UIPasteboard generalPasteboard] setString:address]; + }]; + + [alertController addAction:phone]; + [alertController addAction:copy]; + + } else { + // This type has not been implemented yet. + NI_DASSERT(NO); + NSString* text = [self.mutableAttributedString.string substringWithRange:self.actionSheetLink.range]; + UIAlertAction *copy = [UIAlertAction actionWithTitle:NSLocalizedString(@"Copy", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [[UIPasteboard generalPasteboard] setString:text]; + }]; + [alertController addAction:copy]; + } + + alertController.title = title; + + if (!NIIsPad()) { + + UIAlertAction *cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"") style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + }]; + [alertController addAction:cancel]; + // [actionSheet setCancelButtonIndex:[actionSheet addButtonWithTitle:NSLocalizedString(@"Cancel", @"")]]; + } + + return alertController; +} +#else - (UIActionSheet *)actionSheetForResult:(NSTextCheckingResult *)result { - UIActionSheet* actionSheet = - [[UIActionSheet alloc] initWithTitle:nil - delegate:self - cancelButtonTitle:nil - destructiveButtonTitle:nil - otherButtonTitles:nil]; - - NSString* title = nil; - if (NSTextCheckingTypeLink == result.resultType) { - if ([result.URL.scheme isEqualToString:@"mailto"]) { - title = result.URL.resourceSpecifier; - [actionSheet addButtonWithTitle:NSLocalizedString(@"Open in Mail", @"")]; - [actionSheet addButtonWithTitle:NSLocalizedString(@"Copy Email Address", @"")]; - + UIActionSheet* actionSheet = + [[UIActionSheet alloc] initWithTitle:nil + delegate:self + cancelButtonTitle:nil + destructiveButtonTitle:nil + otherButtonTitles:nil]; + + NSString* title = nil; + if (NSTextCheckingTypeLink == result.resultType) { + if ([result.URL.scheme isEqualToString:@"mailto"]) { + title = result.URL.resourceSpecifier; + [actionSheet addButtonWithTitle:NSLocalizedString(@"Open in Mail", @"")]; + [actionSheet addButtonWithTitle:NSLocalizedString(@"Copy Email Address", @"")]; + + } else { + title = result.URL.absoluteString; + [actionSheet addButtonWithTitle:NSLocalizedString(@"Open in Safari", @"")]; + [actionSheet addButtonWithTitle:NSLocalizedString(@"Copy URL", @"")]; + } + + } else if (NSTextCheckingTypePhoneNumber == result.resultType) { + title = result.phoneNumber; + [actionSheet addButtonWithTitle:NSLocalizedString(@"Call", @"")]; + [actionSheet addButtonWithTitle:NSLocalizedString(@"Copy Phone Number", @"")]; + + } else if (NSTextCheckingTypeAddress == result.resultType) { + title = [self.mutableAttributedString.string substringWithRange:self.actionSheetLink.range]; + [actionSheet addButtonWithTitle:NSLocalizedString(@"Open in Maps", @"")]; + [actionSheet addButtonWithTitle:NSLocalizedString(@"Copy Address", @"")]; + } else { - title = result.URL.absoluteString; - [actionSheet addButtonWithTitle:NSLocalizedString(@"Open in Safari", @"")]; - [actionSheet addButtonWithTitle:NSLocalizedString(@"Copy URL", @"")]; + // This type has not been implemented yet. + NI_DASSERT(NO); + [actionSheet addButtonWithTitle:NSLocalizedString(@"Copy", @"")]; } - - } else if (NSTextCheckingTypePhoneNumber == result.resultType) { - title = result.phoneNumber; - [actionSheet addButtonWithTitle:NSLocalizedString(@"Call", @"")]; - [actionSheet addButtonWithTitle:NSLocalizedString(@"Copy Phone Number", @"")]; - - } else if (NSTextCheckingTypeAddress == result.resultType) { - title = [self.mutableAttributedString.string substringWithRange:self.actionSheetLink.range]; - [actionSheet addButtonWithTitle:NSLocalizedString(@"Open in Maps", @"")]; - [actionSheet addButtonWithTitle:NSLocalizedString(@"Copy Address", @"")]; - - } else { - // This type has not been implemented yet. - NI_DASSERT(NO); - [actionSheet addButtonWithTitle:NSLocalizedString(@"Copy", @"")]; - } - actionSheet.title = title; - - if (!NIIsPad()) { - [actionSheet setCancelButtonIndex:[actionSheet addButtonWithTitle:NSLocalizedString(@"Cancel", @"")]]; - } - - return actionSheet; + actionSheet.title = title; + + if (!NIIsPad()) { + [actionSheet setCancelButtonIndex:[actionSheet addButtonWithTitle:NSLocalizedString(@"Cancel", @"")]]; + } + + return actionSheet; } +#endif - (void)_longPressTimerDidFire:(NSTimer *)timer { - self.longPressTimer = nil; - - if (nil != self.touchedLink) { - self.actionSheetLink = self.touchedLink; - - UIActionSheet* actionSheet = [self actionSheetForResult:self.actionSheetLink]; - - BOOL shouldPresent = YES; - if ([self.delegate respondsToSelector:@selector(attributedLabel:shouldPresentActionSheet:withTextCheckingResult:atPoint:)]) { - // Give the delegate the opportunity to not show the action sheet or to present its own. - shouldPresent = [self.delegate attributedLabel:self shouldPresentActionSheet:actionSheet withTextCheckingResult:self.touchedLink atPoint:self.touchPoint]; - } - - if (shouldPresent) { - if (NIIsPad()) { - [actionSheet showFromRect:CGRectMake(self.touchPoint.x - 22, self.touchPoint.y - 22, 44, 44) inView:self animated:YES]; - } else { - [actionSheet showInView:self]; - } - - } else { - self.actionSheetLink = nil; + self.longPressTimer = nil; + + if (nil != self.touchedLink) { + self.actionSheetLink = self.touchedLink; + +#ifdef IF_IOS8_OR_GREATER + UIAlertController *alertController = [self alertControllerForResult:self.actionSheetLink]; + + BOOL shouldPresent = YES; + if ([self.delegate respondsToSelector:@selector(attributedLabel:shouldPresentAlertController:withTextCheckingResult:atPoint:)]) { + shouldPresent = [self.delegate attributedLabel:self shouldPresentAlertController:alertController withTextCheckingResult:self.touchedLink atPoint:self.touchPoint]; + } + + if (shouldPresent) { + UIViewController *vc = nil; + if ([self.delegate respondsToSelector:@selector(attributedLabel:controllerToPresentAlertController:)]){ + vc = [self.delegate attributedLabel:self controllerToPresentAlertController:alertController]; + } + [vc presentViewController:alertController animated:true completion:nil]; + }else{ + self.actionSheetLink = nil; + } +#else + UIActionSheet* actionSheet = [self actionSheetForResult:self.actionSheetLink]; + + BOOL shouldPresent = YES; + if ([self.delegate respondsToSelector:@selector(attributedLabel:shouldPresentActionSheet:withTextCheckingResult:atPoint:)]) { + // Give the delegate the opportunity to not show the action sheet or to present its own. + shouldPresent = [self.delegate attributedLabel:self shouldPresentActionSheet:actionSheet withTextCheckingResult:self.touchedLink atPoint:self.touchPoint]; + } + + if (shouldPresent) { + if (NIIsPad()) { + [actionSheet showFromRect:CGRectMake(self.touchPoint.x - 22, self.touchPoint.y - 22, 44, 44) inView:self animated:YES]; + } else { + [actionSheet showInView:self]; + } + + } else { + self.actionSheetLink = nil; + } +#endif } - } } - (void)_applyLinkStyleWithResults:(NSArray *)results toAttributedString:(NSMutableAttributedString *)attributedString { @@ -1409,6 +1515,8 @@ - (NSInteger)indexOfAccessibilityElement:(id)element { #pragma mark - UIActionSheetDelegate +#ifdef IF_IOS8_OR_GREATER +#else - (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { if (NSTextCheckingTypeLink == self.actionSheetLink.resultType) { if (buttonIndex == 0) { @@ -1417,7 +1525,7 @@ - (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger) } else if (buttonIndex == 1) { if ([self.actionSheetLink.URL.scheme isEqualToString:@"mailto"]) { [[UIPasteboard generalPasteboard] setString:self.actionSheetLink.URL.resourceSpecifier]; - +  } else { [[UIPasteboard generalPasteboard] setURL:self.actionSheetLink.URL]; } @@ -1456,6 +1564,7 @@ - (void)actionSheetCancel:(UIActionSheet *)actionSheet { self.actionSheetLink = nil; [self setNeedsDisplay]; } +#endif #pragma mark - Inline Image Support