在iOS 7中创建通用搜索文本框(Google和URL)。

3

我们如何创建一个像iOS 7 Safari中的通用搜索文本框。我知道如何创建谷歌搜索字段,但如何创建一个既具有谷歌搜索又具有URL搜索的文本框呢?

谷歌搜索字段:

    -(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];
}

我的Webview控制器:

#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]

2
你是想说如果用户在文本字段中输入类似“facebook”的文本,则应该通过Google进行搜索,如果用户输入“www.facebook.com”,则Web视图应该重定向到Facebook吗? - Salman Zaidi
3个回答

4

在以下情况下,Google Chrome会认为输入的文本是一个URL:

  1. 文本不包含空格(一个单词):
    1. 以有效且被接受的URI协议开头(如httphttpsftp)。
    2. 以斜杠(/)开头。
    3. 以有效的TLD结尾(参见123)。
    4. 以斜杠(/)结尾。
    5. 已知主机名(如localhost)。
    6. 有效的IP地址
  2. 文本包含空格(多个单词):
    1. 以斜杠(/)开头。
  3. 文本包含问号(?),并且可以假定其前面部分是URL。
在其他情况下,您可以安全地假设键入的文本是搜索词。
这不是完整的规则列表,但我认为对于常规用途已经足够了。
主要参考资料:Chromium - Omnibox design principles
更新:
以下是一些提示,可帮助您将先前的规则转换为可工作的代码(顺序很重要):
  • (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])$
    

在移动版Safari中,您可以输入已注册的URI协议,例如“twitter:// ”并启动关联的应用程序。不确定您希望深入了解多少,但这是行为的一部分。https://developer.apple.com/library/IOs/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/AdvancedAppTricks/AdvancedAppTricks.html#//apple_ref/doc/uid/TP40007072-CH7-SW18 - Saltymule

2

使用以下代码。它基本上检查输入到文本字段中的文本。如果它是一个完整的URL,则直接重定向到该URL,否则输入的文本将在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];
}

为了进行额外的检查,您还可以检查url是否有效,就像对其进行ping操作并检查它是否响应一样。


这份代码不能工作,因为当我输入一个URL时它会加载谷歌而非真正的网站。比如说当我输入yahoo.com时它会在谷歌中搜索yahoo.com,而不是前往真正的网站。 - Pixel Code
我已经编辑了答案,并添加了一些额外的工作和检查有效的URL。现在它也可以适用于yahoo.com,google.com等。 - Salman Zaidi

0

您可以创建一个类别:

@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

然后调用类别方法:

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

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

    return YES;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接