转载

使用 Swift 制作一个新闻通知中心插件(2)

我们在第一部分的文章中详细讲解了创建一个通知中心插件的整体过程。我们成功的在通知中心里面显示了新闻列表。但是截止到目前,我们还不能从通知中心的列表中查看新闻的详细内容。在这次的教程中,我们就以上次的教程为基础,继续将我们的通知中心插件的功能改进完善。如果您没有看过第一部分的教程,就请先参看教程的 第一部分

新闻阅读界面

我们在上一篇教程中,已经完成了通知中心插件的新闻列表显示,但是我们点击这个新闻列表中的新闻条目,是没有任何反应的。所以我们在这里需要一个详细页面来显示这个新闻列表。

回到我们的 主应用 中,进入 ViewController.swift 类:

import Foundation import UIKit class ViewController: UIViewController {  var webView:UIWebView?  var newsUrl:String?  override func viewDidLoad() {   self.webView = UIWebView(frame: CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height))   self.view.addSubview(self.webView!)   if(newsUrl != nil){    self.webView?.loadRequest(NSURLRequest(URL: NSURL(string: newsUrl!)!))   }  } }  

这个控制器中,我们创建了一个 UIWebView ,用来显示新闻的内容页面,并加载显示出来。

有了显示视图,我们下一步就要考虑如何从通知中心里面打开这个视图了。

首先我们需要为我们的 App 注册一个 OpenURL ,如果你对 OpenURL 陌生的话,可以查看这篇介绍 http://appurl.org/docs/ios

进入应用设置的 Info 选项中,在里面找打 URL Types 这一项 然后点击下面的加号:

使用 Swift 制作一个新闻通知中心插件(2)

我们按照下图中所示的内容,填写好相关的信息:

使用 Swift 制作一个新闻通知中心插件(2)

我们这里的 OpenURL 的名称叫做 newsapp。

我们设置好这些信息后,就可以安装我们的 app 了。安装好之后,我们在手机端的 Safari 浏览器中输入这个地址:

newsapp://

然后点击确认按钮,你就会发现,系统会识别这个URL类型,并且跳转到我们的 App 中。

使用 Swift 制作一个新闻通知中心插件(2)

跳转到->

使用 Swift 制作一个新闻通知中心插件(2)

这样我们的 OpenURL 跳转流程就完成了。大家可能会发现了,跳转到我们的 app 之后,显示的是一个空白界面。

这是因为我们还没有将新闻的URL地址传递进来。这也是我们接下来要做的。

向 OpenURL 传递参数

我们在刚才,成功的从 Safari 浏览器中通过 OpenURL 跳转到我们的 App 中。那么接下来我们需要将这个跳转操作转移到我们的应用扩展中。

大家如果之前熟悉 App 开发的话,肯定会想到用这个方法来处理 OpenURL :

UIApplication.sharedApplication().openURL("url") 

这是 iOS 原生为我们提供的处理 OpenURL 的方法。但在 Extension 中我们不能使用它。而是用一个叫做 extensionContext 的属性来处理 OpenURL 相关的操作。每一个 Extension 的控制器,都会有这样一个属性 self.extensionContext ,我们使用它来进行 OpenURL 相关的操作。

回到我们 Extension 中的 TodayViewController.swift 中,我们在 tableView:didSelectRowAtIndexPath 方法中加入如下的代码:

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {          tableView.deselectRowAtIndexPath(indexPath, animated: false)         self.extensionContext?.openURL(NSURL(string: "newsapp://")!, completionHandler: nil)       } 

这样,我们在每次在通知中心点击新闻列表的条目后,就会打开我们的主应用。

这个流程就基本完成啦,我们只差最后一部啦。就是我们现在打开的主应用依然是一个空白界面。这是因为我们没有把新闻的URL传递进来。这就是我们接下来要做的工作了。

要传递 OpenURL 的参数,我们只需要对上面的 openURL 调用方法稍加修改:

        var urlString:NSString = NSString(format: "newsapp://?link=%@",link!.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)         self.extensionContext?.openURL(NSURL(string: urlString)!, completionHandler: nil) 

我们看到,为 OpenURL 传递参数的过程,和URL参数的方式基本一样,我们指定了一个参数名为 link 的 URL 参数,将我们的新闻的URL地址作为这个参数的值,并对他用 stringByAddingPercentEscapesUsingEncoding 方法进行URL编码,然后传递给我们的主应用。

现在参数的传递过程就完成了。接下来我们要在我们的主应用中接收这个参数,并用打开它传递进来的URL地址。

现在回到我们主应用的 ViewController.swift 文件中,添加一个 reloadUrl(url:String) 方法:

    func reloadUrl(url:String){          self.webView?.loadRequest(NSURLRequest(URL: NSURL(string: url)!))      } 

这个方法用于刷新 UIWebView 的内容,通过传递进来的 URL 参数来刷新。

最后我们来到具体处理 OpenURL 的地方 AppDelegate.swift 中,我们要添加一个方法 application(application: UIApplication, handleOpenURL url: NSURL) -> Bool , 这个方法用来接收传递进来的 OpenURL

    func application(application: UIApplication, handleOpenURL url: NSURL) -> Bool {  var link:String?  if(url.query!.hasPrefix("link=")){      link = url.query?.stringByReplacingOccurrencesOfString("link=", withString: "", options: nil, range: nil)      link = link?.stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding)  }  (window?.rootViewController as ViewController).reloadUrl(link!)  return true  

我们看到,这个方法的 url 参数,它就是用来接收我们从 Extension 中传递进来的 OpenURL 的。我们这个方法里用了比较简单的字符串操作来取出这个参数(在实际的开发中应该需要更加完善的方式来完成),首先我们用 if(url.query!.hasPrefix("link=")) 来判断 link 参数是否存在。然后将这个参数名从字符串中删除掉 url.query?.stringByReplacingOccurrencesOfString("link=", withString: "", options: nil, range: nil) ,这样删除后的字符串就是我们传递进来的新闻URL地址了。由于这个URL地址是进行过 URL编码的,所以我们还需要用 stringByReplacingPercentEscapesUsingEncoding 方法将它转换回来。

得到了新闻的 URL 之后,我们就可以用这个 URL 来刷新 UIWebView 的显示了,这就用到了我们刚才创建的 reloadUrl 方法:

(window?.rootViewController as ViewController).reloadUrl(link!) 

最后调用 return true 来告诉系统我们自己已经处理了这个 OpenURL 的响应了。

大功告成,现在我们可以运行我们的项目了。 成功运行后我们点击通知中心任意一个新闻条目,就会跳转到我们的主应用,并且加载出相应的页面了:

使用 Swift 制作一个新闻通知中心插件(2)

使用 Swift 制作一个新闻通知中心插件(2)

是不是可以庆祝一下啦��,我们的第一个 App Extension 的基本流程差不多完成了。

不过可以稍等一下,我们还可以稍微再雕琢一下这个 app。首先我们跳转进来后,应用会有几秒钟的时间是一片空白,因为这个时候 UIWebView 在加载网页,所以我们需要一些机制来告诉用户,我们正在进行加载。

那么用什么方式呢? 还记得我们前面提到的 PKHUD 么,这回它派上用场了。

首先,引入 PKHUD :

import PKHUD 

要使用 PKHUD 我们就需要对 ViewController.swift 进行一些修改。 首先要让他实现 UIWebViewDelegate 用来检测 UIWebView 的加载完成事件。

class ViewController: UIViewController,UIWebViewDelegate { 

接下来,需要设置 delegate 属性: self.webView?.delegate = self

然后我们在 viewDidLoad 方法里面初始化 PKHUD ,只需要这两行代码:

        var contentView = HUDContentView.ProgressView()         HUDController.sharedController.contentView = contentView 

初始化完成后,我们需要修改一下 reloadUrl 方法,在开始加载网页的时候显示加载窗口:

    func reloadUrl(url:String){          HUDController.sharedController.show()         self.webView?.loadRequest(NSURLRequest(URL: NSURL(string: url)!))      } 

最后,我们实现 UIWebViewDelegate 的代理方法 webViewDidFinishLoad 用来在网页加载完成的时候关闭加载状态窗口:

    func webViewDidFinishLoad(webView: UIWebView) {          HUDController.sharedController.hide(animated: true)       } 

这样 PKHUD 的集成工作就完成了,下面是修改完成后 ViewController.swift 的完整代码:

import UIKit import PKHUD class ViewController: UIViewController,UIWebViewDelegate {     var webView:UIWebView?     var newsUrl:String?     override func viewDidLoad() {  var contentView = HUDContentView.ProgressView()  HUDController.sharedController.contentView = contentView  self.webView = UIWebView(frame: CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height))  self.webView?.delegate = self  self.view.addSubview(self.webView!)  if(newsUrl != nil){      self.webView?.loadRequest(NSURLRequest(URL: NSURL(string: newsUrl!)!))  }     }     func reloadUrl(url:String){  HUDController.sharedController.show()  self.webView?.loadRequest(NSURLRequest(URL: NSURL(string: url)!))     }     func webViewDidFinishLoad(webView: UIWebView) {  HUDController.sharedController.hide(animated: true)      } }  

这样我们的新闻阅读插件就基本完成了,但这里为止我们介绍了

  1. 如何创建一个 Extension 项目
  2. 如何在 Extension 中读取网络数据
  3. 如何在 Extension 和主应用之间相互通信并传递数据

这个例子只完成了一个基础部分,我们可以在这个基础之上做的更多,同事也欢迎大家发挥自己的想想,来对这个示例进行更进一步的改进与完善。

更多文章请访问: www.theswiftworld.com

正文到此结束
Loading...