Best approach for simple link within UITextView - iphone

I am creating a dictionary lookup application. The user selects a word from a UITableView and the app displays the definition. In some cases the word will be similar to another word, so I want to display "See Also:" followed by a list of similar words that when touched, bring up another definition.
In searching here on links within UITextViews, most of the answers involve linking out to the web, which is not really what I need. I simply want to get control when the user touches a word so that I can change the view.
Is UIWebView the only way to do this, or did I miss something obvious in the SDK? Also, I'd prefer to stay within the native SDK and not go the three20 route.
Thanks!

I would use another UITableView to make this work. Your list of similar words will probably be in NSArray format already, so it would be pretty easy to set up another UITableView instead of a UITextView to display the list, and given that you already have this code working for the main UITableView, you already know how to make them clickable!

A UIWebView will be the only thing that suits here I'm afraid. Data detectors are the only way to link inside of a UITextView, and they will only respond to the appropriate data types (Phone number, web page, address)...
Links can be done the normal way:
<a href='http://someotherword'>someotherword</a>
Setup the webviewdelegate to snag any link requests (and prevent them from being opened in the browser) so that you can open them in your own handler:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
{
if(navigationType == UIWebViewNavigationTypeOther) return YES; // Allow direct loading
NSString *myWord = [[request URL] host];
// do something with myWord... say open another word
return NO; // Don't let the browser actually perform this navigation
}

Related

Opening tel: links from UIWebView

I've searched and searched, but I can't seem to find a fix for this problem.
For some reason, I can not get 'tel:' links to work in a UIWebView. When the links are clicked, the message "The URL can't be shown" appears. Clicking on the same link in Safari works perfectly and dials the number.
This problem started with iOS 5. These links worked perfectly in iOS 4.2 and 4.3.
I'm not sure what other information might be useful, so please let me know if I need to clarify.
Thanks!
EDIT:
Here is the actual code in use...
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = request.URL;
if ([url.scheme isEqualToString:#"tel"]) {
return YES;
}
if (![url.scheme isEqualToString:#"http"] && ![url.scheme isEqualToString:#"https"]) {
if ([[UIApplication sharedApplication] canOpenURL:url]) {
[[UIApplication sharedApplication] openURL:url];
return NO; // Let OS handle this url
}
}
[NSThread detachNewThreadSelector:#selector(startBusy) toTarget:self withObject:nil];
return YES;
}
If I take out the first if statement, the number gets dialed immediately with no confirmation. I'd really like it to function the way it used to by giving an alert, giving you the option to hit either 'Call' or 'Cancel' before dialing the number.
If launching as an HTML link, the tel URL scheme will be opened if they appear as:
1-408-555-5555
If you are launching from a native URL string (meaning you coded this in Objective-C and are not serving it via a WebView), your URL string should look like this:
tel:1-408-555-5555
Note: This only works with iOS devices that have the Phone app installed (that means iPhone only). iPad & iPod Touch devices will display a warning message.
Note 2: Ensure the phone numbers you are passing do not contain spaces or other special characters (such as * and #).
Code Feedback
Based on your code, things are a bit clearer now. You comment about how nothing happens when you leave the first if statement in the shouldStartLoadWithRequest method (where you return YES). This is exactly the behavior you should see because your app is not the Phone app. Only the Phone app can handle the tel: URL scheme. By returning YES, you are telling the OS that your app will handle the phone call, but it cannot. You get the call when that conditional is removed because the next block, which checks if ([[UIApplication sharedApplication] canOpenURL:url]) allows the sharedApplication (which, in this case, is the Phone app) to launch the call.
How Things Work & What You Want
The OS is not going to handle showing the Call/Cancel alert dialog for you. That is up to you. It shows up in Safari because the Safari app's shouldStartLoadWithRequest method undoubtedly responds to the tel: scheme by showing a UIAlertView. Your conditional for if ([url.scheme isEqualToString:#"tel"]) should, when YES, trigger a UIAlertView with a Call and Cancel button. On Call, you will tell the sharedApplication to openURL; on Cancel, you will not issue the call & you will also want to return NO so your app does not attempt to loadWithRequest.
Self-Correcting Edit
To be fair about errors in my own thought process, I'm leaving my responses above.
I believe the Call/Cancel dialog is, in fact, a feature of the OS. Apologies for the inaccuracy.
I'd also erroneously glanced over your code's passing off URL handling to sharedApplication only occurring when the scheme was http or https.
After another look at the code, I wonder if, by any chance you have debug options on in Safari? I believe this prevents the alert from popping up. Also--just to double-check the obvious--you aren't trying this inside the simulator, correct? What happens if you remove the conditional check for http/https and just use the canOpenURL check?
However, aside from the error in my comments on the conditional & dialog itself, you still should not be returning YES. To make a phone call, you should only be able to pull that off by passing it to sharedApplication:openURL and ensuring you return NO because your app is not the Phone app. The only reason you'd want to return YES in this method is if your app is going to handle a tel: link in a special way that doesn't involve sending it to the Phone app.
If you created the UIWebView in a .xib, select the UIWebView and check its attributes in the Attribute Inspector. The first heading should be 'Web View', and under that it provides a list of checkboxes marked 'Detection'. Ensure that 'Phone Numbers' is checked.

How to go back from Safari to UIWebView (iphone)

I really want to thank you all you guys first , I began iOS programming learning several weeks ago ,and I have learnt a lot from here these days,.
I have a UIWebView and loading some html content with "loadHTMLString" method, when i click hyperlinks in the UIwebView, It comforms the
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType{
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
[[UIApplication sharedApplication] openURL:[Request URL]];
return NO;
}
return YES;
}
to open a Safari.
My question is: Can I go back from the Safari to the UIWebView? how?
You can't get Safari to send the user back whenever you want, but one way to get back to your application is by creating a custom URL scheme (e.g. myapp://return, or whatever scheme makes sense to you), assuming that the web page the person is going to can have links that are intended to go back to your appliaction.
You can do this by registering that your application handles the URL scheme, and then processing the request appropriately when iOS tells you to. The Apple docs are fairly complete about this.
But if you want your application to be able to arbitrarily pull people back whenever you want, I don't think that's possible. Safari isn't under the control of anyone but Apple.

ShareKit changes?

I haven't used ShareKit much, but I want to have only three sharing options: Facebook, Twitter, and Email. ShareKit gives far more options, including a More button. However, I don't want the More option, just the three.
In SHKActionSheet.m of ShareKit:
// Add More button
[as addButtonWithTitle:SHKLocalizedString(#"More...")];
It is super easy now, if you use ShareKit 2.0.
edit SHKSharers.plist to include only sharers you need. In case you do not want to compile unused sharers files, check granular install.
You can hide "more..." button in configurator. The new setting is - (NSNumber*)showActionSheetMoreButton
You can disable favourites reordering in configurator. Normally last used sharer is on the top in ShareKit's action sheet. The new setting is - (NSNumber*)autoOrderFavoriteSharers
Using this way you do not need to change or add any code to ShareKit.
I wanted to have the same thing. I spent days to make ShareKit work without too much success. Ok I was able to post FB, Twitter and Email messages but it was more pain the convenience.
Sharekit is an awesome idea but:
You cannot share image, URL and text at the SAME TIME! It has to be
text only, URL only or Image only. Probably you want your user to
post something on FB or Twitter or send an email about your App.
What's the point if the message cannot contain an
App Store or webpage link?
Very badly documented often you have to post questions on
StackoverFlow
It's buggy, not supported by the original designer so there are dozens of forks. You can pick the ShareKit fork, but still.
On it's website it sounds like it's a drag and drop and you can make it work in minutes, good luck for that.
It takes 5 lines to add twitter, about 50 for Facebook and email to support text, URL and photo at the same time.
Twitter: This code sends a message with User editable text, URL (hidden, not editable) and an image. It took me 5 minutes to figure it out.
#import <Twitter/TWTweetComposeViewController.h>
- (IBAction)twitterButton:(id) sender {
TWTweetComposeViewController *tweetView = [[TWTweetComposeViewController alloc] init];
[tweetView setInitialText:#"Check out this app, it's awesome" ];
[tweetView addImage:[UIImage imageNamed:#"MyImage.png"]];
[tweetView addURL:[NSURL URLWithString:appDelegate.appStoreURL]];
[self presentModalViewController:tweetView animated:YES];
}
I really appreciate the effort of creating Sharkit but personally I cannot recommended it unless you really need to support all of those sharers and you happy with limited functionality.
UPDATE:
I implemented Facebook sharing myself. It was more difficult than I thought. The main problem is that you cannot upload a photo with a post because Facebook only accept image links. Even worse Facebook does not allow to link to a photo which is uploaded to the user photo album (very easy) as it must be an external link. For static images you can use a URL shortener to get around it but for user generated images pretty much you have to use Amazon S3 or something else. Amazon S3 is super easy to use, I figured out how to use upload files in an hour or so.
If you don't want the More... button, why don't you take out the line of code that adds it?
you need to make this code changes from SHKActionSheet.m
+ (SHKActionSheet *)actionSheetForType:(SHKShareType)type
// Add More button
//[as addButtonWithTitle:SHKLocalizedString(#"More...")];
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
// More
// else if (buttonIndex == sharers.count)
// {
// SHKShareMenu *shareMenu = [[SHKCustomShareMenu alloc]
// initWithStyle:UITableViewStyleGrouped];
// shareMenu.item = item;
// [[SHK currentHelper] showViewController:shareMenu];
// [shareMenu release];
// }
And you can edit SHKSharers.plist for services you like.
you can use the below definition for dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
you need to delete the few lines which is commented in the below definition.
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
{
// Sharers
if (buttonIndex >= 0 && buttonIndex < sharers.count)
{
[NSClassFromString([sharers objectAtIndex:buttonIndex]) performSelector:#selector(shareItem:) withObject:item];
}
// More
//else if (buttonIndex == sharers.count)
// {
// SHKShareMenu *shareMenu = [[SHKCustomShareMenu alloc] initWithStyle:UITableViewStyleGrouped];
// shareMenu.item = item;
// [[SHK currentHelper] showViewController:shareMenu];
// [shareMenu release];
// }
[super dismissWithClickedButtonIndex:buttonIndex animated:animated];
}
Excellent solution, however in my case for example want to use Facebook as well and there is no way to share content natively in iOS5. Another problem is that those who need the app compatible with iOS4.0 or higher (my case) can not, because this method only works from 5.0.
How to solve this? ShareKit to Use Facebook and Twitter for the native methods and forget about compatibility with iOS4.0?

detecting URL and format it in UITextField

I would like to be able to format a URL in my UITextField nicely. So say the text of the UITextField is
textField.text = #"Hi this is a page for my website http://www.mywebsite.com";
I would like it to automatically underline this mark it as a hyperlink and when a user taps on the link it opens up the site. This is similar to any twitter client that you have out there (tweetdeck, tweetbot, etc). How do I do this the easy way?
You can use a UITextView instead and set the dataDetectorTypes property to the types of links you want to be able to handle.
hey this is really simple, you can set the UITextFiled to detect Links, like so:
myTextView.dataDetectorTypes = UIDataDetectorTypeAll
check out my tutorial on this at my site for more info
http://www.sdkboy.com

How do I know if text contains URL links (UIWebView)

I have some text which might or might not contain web URLs, phone numbers, email links etc. which UIWebView automatically detects as hotspots.
Question: I want to show this text in UIWebView ONLY when there are one or more hotspots, but as plain text if it doesn't. So how can I detect this in code?
Additional Info: JavaScript code below tells how many ... links there are. This does NOT count how many other "link" items there are. For example "Link to www.yle.fi" contains one link according to UIWebView, but zero according to JavaScript:
NSString *s = [webView stringByEvaluatingJavaScriptFromString:
#"document.links.length"];
Still no answer to the question how to ask UIWebView how many links it has found...
You can use several regular expressions and check if the text matches those of URL/phone number/email addresses.
However, if your intention is simply let the user open a link, the UITextView is suffice.
Check the dataDetectorTypes property.