如何从iOS应用程序启动Safari并打开URL

226
在设置页面上,我想包含三个链接:
  • 我的应用支持网站
  • YouTube应用教程
  • 我的主要网站(即:连接到“由Dale Dietrich创建”的标签。)
我已经在该网站、网络和文档中进行了搜索,但没有找到明显的方法。
注意:我不想在我的应用程序内打开网页。我只想发送链接到Safari,然后在那里打开该链接。我已经看到许多应用程序在它们的设置页面中执行同样的操作,因此这一定是可能的。

我在使用Ionic Cordova应用程序进行混合开发时遇到了同样的问题。 - Sopo
15个回答

397

这是我所做的:

  1. 我在头文件.h中创建了一个IBAction,如下所示:

  2.  - (IBAction)openDaleDietrichDotCom:(id)sender;
    
  3. 我在设置页面添加了一个UIButton,其中包含我想要链接到的文本。

  4. 我正确地将按钮连接到文件所有者中的IBAction。

  5. 然后按照以下步骤进行实现:

Objective-C

- (IBAction)openDaleDietrichDotCom:(id)sender {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.daledietrich.com"]];
}

Swift

在视图控制器中使用 IBAction,而不是在头文件中使用 IBAction。

if let link = URL(string: "https://yoursite.com") {
  UIApplication.shared.open(link)
}

请注意,我们不需要转义字符串或地址,例如:

let myNormalString = "https://example.com";
let myEscapedString = myNormalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!

实际上,转义可能会导致打开失败。


9
但这并非百分之百确定,因为如果有人使用越狱的iOS并将Chrome或其他浏览器设置为默认浏览器,那么打开链接时会使用该浏览器而不是Safari。 - Laszlo
225
我感觉如果有人费心越狱把Chrome设置为默认浏览器,尊重这个设定可能是最理想的行为。 - rpowell
我理解了这个问题,但是如果我正在打开一个网站并且用户正在浏览该网站,现在如果他停留在某个页面上,那么我能否在我的代码中获取当前网页链接? - Varun Jain
3
现在上述方法已经被弃用,请使用以下方式: [[UIApplication sharedApplication] openURL:[NSURL URLWithString:self.advertisement.url] options:@{} completionHandler:^(BOOL success) {}]; - Mashhadi
@Laszlo 同样,在设置中,我们可以在“限制”中禁用Safari。我编写了一个应用程序,使用URL方案http和https,在打开http或https URL并禁用Safari时打开其他浏览器。因此,即使没有越狱,我们也可以在技术上更改默认的Web浏览器。 - Emma Labbé

172

Swift语法:

UIApplication.sharedApplication().openURL(NSURL(string:"http://www.reddit.com/")!)

iOS 9.3及之前版本的新Swift语法

在某个新版Swift(可能是Swift 2?)中,UIApplication.sharedApplication()现在变成了UIApplication.shared(我猜是更好地利用计算属性)。此外,URL不再可以隐式转换为NSURL,必须使用as!进行显式转换。

UIApplication.sharedApplication.openURL(NSURL(string:"http://www.reddit.com/") as! URL)

iOS 10.0新的Swift语法

自iOS 10.0起,openURL方法已被弃用并替换为更多功能的方法,该方法接受一个选项对象和一个异步完成处理程序。

UIApplication.shared.open(NSURL(string:"http://www.reddit.com/")! as URL)

31
对于Swift开发人员而言,Swift版的答案非常有用。由于Swift是一门新语言,缺少很多关于解决实际iOS问题的文档,因此涉及到实际问题时,特别需要Swift版本的答案。在我的情况下,自动填充选择了“fileURLWithPath:”选择器,我没有意识到这就是为什么我的URL无法打开的原因,只有通过阅读达斯汀的答案,我才知道我应该使用“string:”选择器。所以应该支持达斯汀,而不是责备他。 - SafeFastExpressive
3
为什么他不能包括一个Swift版本? - ericgu
2
openURL(_:)在iOS 10.0中已被弃用,您应该在UIApplication上调用实例方法open(_:options:completionHandler:) - Ryan H.
2
你可以直接使用URL而不是NSURL,这样可以节省转换的时间。 - marsbear
1
我建议永远不要强制解包。if let url = NSURL(string:"http://www.reddit.com/") { UIApplication.shared.open(url) }这种写法总是更好。你可能想在else语句中使用assert和错误处理来捕获拼写错误。 - philipp

55

这里需要进行一个检查,看所要打开的URL是否可以在设备或模拟器上打开。因为有时候(主要在模拟器上)我发现它会导致崩溃。

Objective-C

NSURL *url = [NSURL URLWithString:@"some url"];
if ([[UIApplication sharedApplication] canOpenURL:url]) {
   [[UIApplication sharedApplication] openURL:url];
}

Swift 2.0

let url : NSURL = NSURL(string: "some url")!
if UIApplication.sharedApplication().canOpenURL(url) {
     UIApplication.sharedApplication().openURL(url)
}

Swift 4.2

guard let url = URL(string: "some url") else {
    return
}
if UIApplication.shared.canOpenURL(url) {
    UIApplication.shared.open(url, options: [:], completionHandler: nil)
}

1
你可以随时打开HTTP/HTTPS。从iOS 9开始,您需要将任何想要调用canOpenURL的URL列入白名单。我不明白为什么您不直接调用openURL:url,如果失败了,再处理失败。canOpenURL主要用于检测应用程序的安装情况,而不离开当前应用程序。 - Ben Flynn
1
openURL(_:)在iOS 10.0中已被弃用,您应该在UIApplication上调用实例方法open(_:options:completionHandler:) - Ryan H.

21

请查看UIApplication的-openURL:方法。它应该允许您将NSURL实例传递给系统,系统将确定要在哪个应用程序中打开它并启动该应用程序。(请记住,您可能需要首先检查-canOpenURL:,以防URL无法由当前安装在系统上的应用程序处理 - 尽管这对于纯粹的http://链接可能不是问题。)


谢谢Tim。你说得很对。我正在添加我的答案,而你的答案也同时出现了。对此我感到抱歉。但至少现在有一个简单的如何操作指南供那些跟随我的人使用。 - Dale Dietrich
没问题 - 很高兴你找到了解决方案! - Tim
1
在iOS 10.0中,openURL(_:)已被弃用,你应该在UIApplication上调用实例方法open(_:options:completionHandler:) - Ryan H.

17

如果您不确定提供的URL text 是否具有方案,请参考以下内容:

NSString* text = @"www.apple.com";
NSURL*    url  = [[NSURL alloc] initWithString:text];

if (url.scheme.length == 0)
{
    text = [@"http://" stringByAppendingString:text];
    url  = [[NSURL alloc] initWithString:text];
}

[[UIApplication sharedApplication] openURL:url];

@Vlad 这只是一个硬编码的例子。通常url字符串(这里的text)不会被硬编码,你需要像这样的代码。 - meaning-matters
@Vlad 你感到沮丧了吗?如果是的话,是如何/为什么?我猜想人们不会只是复制粘贴上面的代码。 - meaning-matters
1
意义至上 - Vlad

16

非废弃的Objective-C版本是:

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://apple.com"] options:@{} completionHandler:nil];

11

Swift 3带有一个“完成”按钮的解决方案

不要忘记import SafariServices

if let url = URL(string: "http://www.yoururl.com/") {
            let vc = SFSafariViewController(url: url, entersReaderIfAvailable: true)
            present(vc, animated: true)
        }

这是一个完美的答案,可以在iOS和iOS扩展中使用。其他答案只适用于应用程序,无法在扩展中使用。 - Owen Zhao

10

Swift 3.0

->

Swift 3.0

if let url = URL(string: "https://www.reddit.com") {
    if #available(iOS 10.0, *) {
        UIApplication.shared.open(url, options: [:])
    } else {
        UIApplication.shared.openURL(url)
    }
}

这也支持运行较旧版本 iOS 的设备


5

因为自iOS 10.0起,此答案已被弃用,更好的答案是:

if #available(iOS 10.0, *) {
    UIApplication.shared.open(url, options: [:], completionHandler: nil)
}else{
    UIApplication.shared.openURL(url)
}

并且使用 Objective-C

[[UIApplication sharedApplication] openURL:@"url string" options:@{} completionHandler:^(BOOL success) {
        if (success) {
            NSLog(@"Opened url");
        }
    }];

4

Swift 5:

func open(scheme: String) {
   if let url = URL(string: scheme) {
      if #available(iOS 10, *) {
         UIApplication.shared.open(url, options: [:],
           completionHandler: {
               (success) in
                  print("Open \(scheme): \(success)")
           })
     } else {
         let success = UIApplication.shared.openURL(url)
         print("Open \(scheme): \(success)")
     }
   }
 }

用法:

open(scheme: "http://www.bing.com")

参考资料:

iOS10中的OpenURL


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