3

How do we create a universal search textfield like in iOS 7 safari. I know how to create a Google search field, but how can I create one textfield which has both Google search and URL search.

Google Searchfield:

    -(void)SearchButtonClicked {

        NSString *query = [maintext.text stringByReplacingOccurrencesOfString:@" " withString:@"+"];
        NSString *urlString = [NSString stringWithFormat:@"%@", query];

        // remember to change the view controller class in storyboard
        MyWebViewController *webViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"WebView"];

        // urlString is a public property on MyWebViewController
        webViewController.urlString = urlString;
        [self presentViewController:webViewController animated:YES completion:nil];  
    }

    - (IBAction)SearchButton:(id)sender {

        NSString *query = [maintext.text stringByReplacingOccurrencesOfString:@" " withString:@"+"];
        NSString *urlString = [NSString stringWithFormat:@"http://www.google.com/search?q=%@", query];

        // remember to change the view controller class in storyboard
        MyWebViewController *webViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"WebView"];

        // urlString is a public property on MyWebViewController
        webViewController.urlString = urlString;
        [self presentViewController:webViewController animated:YES completion:nil];
}

My Webview controller:

#import "MyWebViewController.h"
#import "ViewController.h"
#import <Social/Social.h>
#import "SIAlertView.h"
#import "TTAlertView.h"

#import "ETActivityIndicatorView.h"



@implementation MyWebViewController {


}

@synthesize searchField;

@synthesize webView;

ETActivityIndicatorView * etActivity;

- (void)viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];

    NSURL *url = [NSURL URLWithString:self.urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [self.webView loadRequest:request];



}

-(void)webView:(UIWebView *)webBlog didFailLoadWithError:(NSError *)error{

    if ([error code] != -999) {
        NSLog(@"Could not load the dumb webPage");
        //show error alert, etc.

        TTAlertView *alert = [[TTAlertView alloc] initWithTitle:@"Internet Error"
                                                        message:@"Searched cannot open the page because your iPhone is not connected to the internet."
                                                       delegate:self
                                              cancelButtonTitle:@"Dismiss"
                                              otherButtonTitles:nil];

        [alert show];

        [etActivity setHidden:YES];


    }else{

        NSLog(@"Could not load the dumb web page...just might blame user!");
    }
}


//Called whenever the view starts loading something
- (void)webViewDidStartLoad:(UIWebView *)webView {
    [etActivity startAnimating];

    [etActivity setHidden:NO];
}

//Called whenever the view finished loading something
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    [etActivity stopAnimating];

    [etActivity setHidden:YES];

}



- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [webView setDelegate:self];

    self.searchField.backgroundColor = [UIColor colorWithRed:255.0/255 green:255.0/255 blue:255.0/255 alpha:1.0f];
    self.searchField.layer.cornerRadius = 3.0f;
    self.searchField.placeholder = @"Search or enter address";
    self.searchField.leftViewMode = UITextFieldViewModeAlways;
    UIView* leftView1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
    self.searchField.leftView = leftView1;

    //Setup handling of LEFT and RIGHT swipes
    UISwipeGestureRecognizer *recognizer;

    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    [recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
    [[self view] addGestureRecognizer:recognizer];


    recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
    [recognizer setDirection:(UISwipeGestureRecognizerDirectionLeft)];
    [[self view] addGestureRecognizer:recognizer];

    self.searchField.delegate = self;

    //ETActivityIndicatorView
    etActivity = [[ETActivityIndicatorView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 60.0f, 60.0f)];

    etActivity.center=self.view.center;

    //you can set your custom color for ETActivityIndicatorView
    etActivity.color = [UIColor colorWithRed:13.0/255 green:136.0/255 blue:236.0/255 alpha:1.0f];

    [self.view addSubview:etActivity];
}


-(void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer {

    if (recognizer.direction == UISwipeGestureRecognizerDirectionRight) {
        NSLog(@"Swipe Right");
          [webView goBack];
    }

    if (recognizer.direction == UISwipeGestureRecognizerDirectionLeft) {
        NSLog(@"Swipe Left");
         [webView goForward];
    }

}


#pragma mark - RNGridMenuDelegate
- (void)gridMenu:(RNGridMenu *)gridMenu willDismissWithSelectedItem:(RNGridMenuItem *)item atIndex:(NSInteger)itemIndex {

    if (itemIndex == 0) {
        NSLog(@"Reload");

        [self.webView reload];
    }

    if (itemIndex == 1) {
        NSLog(@"Facebook");

        if([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) //check if Facebook Account is linked
        {
            mySLComposerSheet = [[SLComposeViewController alloc] init]; //initiate the Social Controller
            mySLComposerSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook]; //Tell him with what social plattform to use it, e.g. facebook or twitter
            [mySLComposerSheet setInitialText:[NSString stringWithFormat:@""]]; //the message you want to post

                       [self presentViewController:mySLComposerSheet animated:YES completion:nil];
        }
        [mySLComposerSheet setCompletionHandler:^(SLComposeViewControllerResult result) {

            switch (result) {
                case SLComposeViewControllerResultCancelled:

                    break;
                case SLComposeViewControllerResultDone:

                    break;
                default:
                    break;
            } //check if everything worked properly. Give out a message on the state.

        }];



    }
    if (itemIndex == 2) {

        if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
        {
            SLComposeViewController *tweetSheet = [SLComposeViewController
                                                   composeViewControllerForServiceType:SLServiceTypeTwitter];
            [tweetSheet setInitialText:@""];
            [self presentViewController:tweetSheet animated:YES completion:nil];
        }

    }

    if (itemIndex == 3) {
        NSLog(@"Home");

        MyWebViewController *MainView = [self.storyboard instantiateViewControllerWithIdentifier:@"MainView"];
        [self presentViewController:MainView animated:NO completion:nil];

    }

}




- (void)showList {
    NSInteger numberOfOptions = 4;
    NSArray *options = @[
                         @"Reload",
                         @"Facebook",
                         @"Twitter",
                         @"Home",

                         ];
    RNGridMenu *av = [[RNGridMenu alloc] initWithTitles:[options subarrayWithRange:NSMakeRange(0, numberOfOptions)]];
    av.delegate = self;
    av.itemFont = [UIFont boldSystemFontOfSize:18];
    av.itemSize = CGSizeMake(150, 55);
    [av showInViewController:self center:CGPointMake(self.view.bounds.size.width/2.f, self.view.bounds.size.height/2.f)];
}


- (IBAction)onShowButton:(id)sender {
    [self showList];
}


![enter image description here][1]
BenMorel
  • 34,448
  • 50
  • 182
  • 322
Pixel Code
  • 169
  • 1
  • 13
  • 2
    Are you trying to say that if user enters text like "facebook" in text field, then it should be searched through google and if user enters "www.facebook.com", then web view should be redirected to facebook??? – Salman Zaidi Oct 01 '13 at 07:22

3 Answers3

4

Google Chrome assumes the typed text is a URL in these cases:

  1. Text contains no whitespaces (One word):
    1. Starts with a valid and accepted URI scheme (Like http, https, and ftp).
    2. Starts with a forward slash (/).
    3. Ends with a valid TLD (See 1, 2, 3).
    4. Ends with a forward slash (/).
    5. Known hostnames (Like localhost).
    6. Valid IP addresses.
  2. Text contains whitespaces (Multiple words):
    1. Starts with a forward slash (/).
  3. Text contains a question mark (?) and the part before it can be assumed a URL.

In all other cases you can safely assume the typed text is a search term.

This isn't a complete list of rules, but I think it's more than enough for regular usage.

Main reference: Chromium - Omnibox design principles.

Update:

Here are some hints to help you convert the previous rules to a working code (the order is important):

  • (Rule 3) Replace the part of text that matches this regular expression:

    \?.*$
    

    with empty string @"", and then apply other rules.

  • (Rules 1.1, 1.2, 1.4, 1.5, and 2.1) Match against this regular expression:

    ^((\/)|((https?|ftp):\S+$)|(\S+\/$)|(localhost$))
    
  • (Rule 1.3) You can collect some popular TLDs from the links above and form a one regular expression from them like this:

    \S+\.(com|net|org|....)$
    
  • (Rule 1.6) Match against this regular expression:

    ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9‌​]{2}|2[0-4][0-9]|25[0-5])$
    
Community
  • 1
  • 1
Hejazi
  • 16,587
  • 9
  • 52
  • 67
  • On Mobile Safari, you can enter a registered URI scheme, such as "twitter://" and launch the associated app. Not sure how deep you wanted to go with this, but it is part of the behavior. https://developer.apple.com/library/IOs/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/AdvancedAppTricks/AdvancedAppTricks.html#//apple_ref/doc/uid/TP40007072-CH7-SW18 – Saltymule Oct 11 '13 at 20:40
2

Use this code. This basically checks the text entered into the textfield. If it's a complete url, then it redirects directly to it else the text entered is searched on google.

- (IBAction)SearchButton:(id)sender 
{
    MyWebViewController *webViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"WebView"];

    NSString *urlString = maintext.text;
    if([urlString rangeOfString:@"//"].location == NSNotFound)
    {
        // to resolve a url according to rfc 1808 (the most common form of URL), it must contain '//' in it.
        // appending '//' in the url string to check for valid url
        urlString = [NSString stringWithFormat:@"//%@", urlString];
    }

    NSURL *url = [NSURL URLWithString:urlString];
    if(url && (url.scheme || url.host) && ([urlString rangeOfString:@"."].location != NSNotFound))
    {
       // url is valid, it contains domain and host
        webViewController.urlString = maintext.text;
    }
    else 
    {
        NSString *query = [maintext.text stringByReplacingOccurrencesOfString:@" " withString:@"+"];
        NSString *urlString = [NSString stringWithFormat:@"http://www.google.com/search?q=%@", query];

        // urlString is a public property on MyWebViewController
        webViewController.urlString = urlString;
    }

    [self presentViewController:webViewController animated:YES completion:nil];
}

For, extra checks, you can also check that the url is valid or not like pinging to it and checking for it whether it responds or not.

Salman Zaidi
  • 9,342
  • 12
  • 44
  • 61
  • This code doesn't work because, when I type a URL it loads it Google. Like if I type yahoo.com it will search Google for yahoo.com, not go to the website yahoo.com. – Pixel Code Oct 02 '13 at 01:36
  • I have edited the answer and added some extra work and checks for valid url. now it will work for yahoo.com, google.com, etc too.. – Salman Zaidi Oct 02 '13 at 05:10
0

You can create a category:

@interface NSString (NSStringValidator)
- (BOOL)isValidEmail;
- (BOOL)isValidURL;
@end

@implementation NSString (NSStringValidator)
- (BOOL)isValidEmail {
    NSString *regExpPattern = @"\\b([a-zA-Z0-9%_.+\\-]+)@([a-zA-Z0-9.\\-]+?\\.[a-zA-Z]{2,6})\\b";

    NSError *errorNext = NULL;
    NSRegularExpression *regexNext = [NSRegularExpression regularExpressionWithPattern:regExpPattern
                                                                               options:NSRegularExpressionCaseInsensitive
                                                                                 error:&errorNext];
    NSRange range = [regexNext rangeOfFirstMatchInString:self
                                                 options:NSRegularExpressionCaseInsensitive
                                                   range:NSMakeRange(0, self.length)];
    return NSEqualRanges(range, NSMakeRange(0, self.length));
}

- (BOOL)isValidURL {
    NSString *regExpPattern = @"(?i)(?:(?:https?):\\/\\/)?(?:\\S+(?::\\S*)?@)?(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:\\/[^\\s]*)?";

    NSError *errorNext = NULL;
    NSRegularExpression *regexNext = [NSRegularExpression regularExpressionWithPattern:regExpPattern
                                                                               options:NSRegularExpressionCaseInsensitive
                                                                                 error:&errorNext];
    NSRange range = [regexNext rangeOfFirstMatchInString:self
                                                 options:NSRegularExpressionCaseInsensitive
                                                   range:NSMakeRange(0, self.length)];
    return NSEqualRanges(range, NSMakeRange(0, self.length));
}
@end

Then call category method:

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField
{
    [theTextField resignFirstResponder];

    if (theTextField.text.isValidURL) {
        //open site
    } else {
        //search text
    }

    return YES;
}