草庐IT

ios - 点击本地通知打开特定的 View Controller

coder 2024-01-22 原文

标题说明了一切。我浏览了很多帖子,试图找到一个解决方案,但没有成功......

我有一个通知,我不确定它的名字...

let request = UNNotificationRequest(identifier: "timerDone", content: content, trigger: trigger)

q1:名称是 timerDone 吗?

viewDidLoad() 中:

NotificationCenter.default.addObserver(self,
                                                         selector: "SomeNotificationAct:",
                                                         name: NSNotification.Name(rawValue: "timerDone"),
                                                         object: nil)

然后我有这个方法:

@objc func SomeNotificationAct(notification: NSNotification){
        DispatchQueue.main.async() {
            self.performSegue(withIdentifier: "NotificationView", sender: self)
        }
    }

AppDelegate.swift 中使用这个:

private func application(application: UIApplication, didReceiveRemoteNotification userInfo: Any?){

    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "SomeNotification"), object:nil)
}

任何想法如何做到这一点?提前致谢!

更新:@Sh_Khan

首先,我正在用 swift 编写代码,我尝试将您的代码从 obj-c 转换为 swift 如下:

if (launchOptions![UIApplicationLaunchOptionsKey.localNotification] != nil)
{
    var notification =
        launchOptions![UIApplicationLaunchOptionsKey.localNotification]
    [self application:application didReceiveLocalNotification:notification]; //how to translate?
}

最后一行应该翻译成什么?

当你写的时候:

应该在 didReceiveLocalNotification 方法中的用户默认值中存储一个 bool 变量,并在 rootViewcontroller 的 viewDidAppear 方法中检查它以生成 segue,然后将其设为 false,因为 notificationCenter 仅在应用程序处于前台或后台时才起作用,如果还没有暂停

假设 bool 值是 notiView,当我们收到本地通知时将其设置为 true,因此转场将转到一个不同 View Controller 。这是你的意思吗?

最佳答案

我发现用户通知文档有点困惑和不完整。这些教程比大多数其他 Apple 框架都要好。然而,这些教程大多是不完整的,并且假设每个应用程序都在 AppDelegate 中实现了通知中心委托(delegate)。不!

对于许多在 View Controller 中(而不是在 AppDelegate 中)处理通知委托(delegate)的应用程序,需要在 AppDelegate didFinishLaunchingWithOptions 方法中将 View Controller 设置为用户通知中心委托(delegate)。否则,当您的应用程序从后台模式启动时,通知代理将看不到您的通知触发。您的 View Controller 在通知触发后加载。您需要一种在 View Controller 完成加载后启动委托(delegate)方法的方法。

例如:假设您正在使用一个 Split View Controller 作为您应用程序的初始 View Controller ,并且您已经将拆分 VC 的主视图 Controller 实现为您的通知代理,您需要让 UNUserNotificationCenter 知道主 VC 是它的当您的应用程序启动时委托(delegate)(不是像大多数教程建议的那样在主 VC 的 viewDidLoad() 内部)。例如,

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        ...
        let splitViewController = window!.rootViewController as! UISplitViewController
        ...
        if #available(iOS 10.0, *) {
            if let masterViewController = splitViewController.viewControllers.first as? MasterViewController {
                UNUserNotificationCenter.current().delegate = masterViewController
            }
        }
    }

当您的应用冷启动或从后台模式启动时,这将允许 iOS 在主 VC 加载后调用您的通知委托(delegate)方法。

此外,如果您需要您的主 VC 知道它是由于用户通知触发(而不是正常加载)而加载的,您将使用 NSUserDefaults 来传达此信息。因此,AppDelegate 将如下所示:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    ...
    let splitViewController = window!.rootViewController as! UISplitViewController
    ...
    if #available(iOS 10.0, *) {
        if let _ = launchOptions?[UIApplicationLaunchOptionsKey.localNotification] {
            UserDefaults.standard.set("yes", forKey: kMyAppLaunchedByUserNotification)
            UserDefaults.standard.synchronize()
        }
        if let masterViewController = splitViewController.viewControllers.first as? MasterViewController {
            UNUserNotificationCenter.current().delegate = masterViewController
        }
    }
}

其中 kMyAppLaunchedByUserNotification 是您用来与主 VC 通信的 key 。在 Master View Controller 的 viewDidAppear() 中,您将检查 User Defaults 以查看它是否因通知而被加载。

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    if #available(iOS 10.0, *) {
        if let _ = UserDefaults.standard.object(forKey: kMyAppLaunchedByUserNotification) {
            UserDefaults.standard.removeObject(forKey: kMyAppLaunchedByUserNotification)
            UserDefaults.standard.synchronize()
            //Handle any special thing that you need to do when your app is launched from User notification as opposed to regular app launch here
            // NOTE: the notification delegate methods will be called after viewDidAppear() regardless of you doing any special thing here because you told iOS already in AppDelegate didFinishLaunchingWithOptions
        }
    }
}

希望对你有帮助

关于ios - 点击本地通知打开特定的 View Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47734432/

有关ios - 点击本地通知打开特定的 View Controller的更多相关文章

  1. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  2. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  3. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  4. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  5. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  6. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  7. ruby-on-rails - 如何在发布新的 Ruby 或 Rails 版本时收到通知? - 2

    有人知道在发布新版本的Ruby和Rails时收到电子邮件的方法吗?他们有邮件列表,RubyonRails有一个推特,但我不想听到那些随之而来的喧嚣,我只想知道什么时候发布新版本,尤其是那些有安全修复的版本。 最佳答案 从therailsblog获取提要.http://weblog.rubyonrails.org/feed/atom.xml 关于ruby-on-rails-如何在发布新的Ruby或Rails版本时收到通知?,我们在StackOverflow上找到一个类似的问题:

  8. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  9. Ruby - 如何在读取文件时跳过/忽略特定行? - 2

    在读取/解析文件(使用Ruby)时忽略某些行的最佳方法是什么?我正在尝试仅解析Cucumber.feature文件中的场景,并希望跳过不以Scenario/Given/When/Then/And/But开头的行。下面的代码有效,但它很荒谬,所以我正在寻找一个聪明的解决方案:)File.open(file).each_linedo|line|line.chomp!nextifline.empty?nextifline.include?"#"nextifline.include?"Feature"nextifline.include?"Inorder"nextifline.include?

  10. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

随机推荐