Skip to content

iOS 8 Support #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
23 changes: 23 additions & 0 deletions src/NIAttributedLabel.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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

Expand Down
237 changes: 173 additions & 64 deletions src/NIAttributedLabel.m
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ - (CGSize)boxSize {

@end

#ifdef IF_IOS8_OR_GREATER
@interface NIAttributedLabel()
#else
@interface NIAttributedLabel() <UIActionSheetDelegate>
#endif

@property (nonatomic, strong) NSMutableAttributedString* mutableAttributedString;

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand All @@ -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];
}
Expand Down Expand Up @@ -1456,6 +1564,7 @@ - (void)actionSheetCancel:(UIActionSheet *)actionSheet {
self.actionSheetLink = nil;
[self setNeedsDisplay];
}
#endif

#pragma mark - Inline Image Support

Expand Down