Ios 在Swift上以编程方式将应用程序置于前台

Ios 在Swift上以编程方式将应用程序置于前台,ios,swift,foreground,Ios,Swift,Foreground,我测试了: UIControl().sendAction(#selector(URLSessionTask.suspend), to: UIApplication.shared, for: nil) 这是为了把应用程序放在后台,它可以工作 如何将应用程序放回前台 我试过: UIControl().sendAction(#selector(URLSessionTask.resume), to: UIApplication.shared, for: nil) 但最终它崩溃了 谢谢更新: 由于您已

我测试了:

UIControl().sendAction(#selector(URLSessionTask.suspend), to: UIApplication.shared, for: nil)
这是为了把应用程序放在后台,它可以工作

如何将应用程序放回前台

我试过:

UIControl().sendAction(#selector(URLSessionTask.resume), to: UIApplication.shared, for: nil)
但最终它崩溃了


谢谢

更新:

由于您已表示正在寻找任何技术解决方案,即使是那些与App Store或Apple的条款不兼容的技术解决方案,这应该可以使用私有API
LSApplicationWorkspace:openApplicationWithBundleID
。试着这样做:

创建一个.h文件并设置到
LSApplicationWorkspace
类的接口,并列出所需的方法。您需要在桥接头中导入“PrivateHeaders.h”

//
// PrivateHeaders.h
//

#ifndef PrivateHeaders_h
#define PrivateHeaders_h

@interface LSApplicationWorkspace : NSObject

- (bool)openApplicationWithBundleID:(id)arg1;

@end

#endif /* PrivateHeaders_h */
然后,您应该能够调用此函数并将应用程序的捆绑包标识符作为字符串传递

//
// SomeClass.swift
//

import MobileCoreServices

let workspace = LSApplicationWorkspace()

/**
 Launch an App given its bundle identifier
 - parameter bundleIdentifier: The bundle identifier of the app to launch
 - returns: True if app is launched, otherwise false
 */
func openApp(withBundleIdentifier bundleIdentifier: String) -> Bool {
    // Call the Private API LSApplicationWorkspace method
    return workspace.openApplication(withBundleID: bundleIdentifier)
}
原件:

您所做的很可能违反了(尽管“不要以编程方式退出”不再是专门定义的),因此正如评论所说,它不适合应用商店。无论如何,一旦你的应用程序以这种方式挂起,我不希望有一种方式以编程方式恢复它,除非你可以挂接到一个运行
URLSessionTask.resume
,但我还没有测试过它,也不确定它是否能工作

应用程序可以通过编程方式从另一个应用程序或today扩展启动(并因此进入前台),方法是使用或通过。无法通过URL方案从后台操作启动应用程序,因为它是UIKit框架的一部分,必须在主线程中运行


总之,我认为您最好的选择是尝试使用通知。这仅仅意味着用户需要点击通知才能将你的应用程序带回到前台。

作为Jordan出色回答的后续,我想解释一下为什么你的代码首先有效,以及为什么仅此一项就会导致你的应用程序被拒绝,即使没有任何功能使其再次激活并将其置于前台

正如maddy在评论中指出的,您基本上是从
UIApplication
的私有API调用方法。这是由于Objective-C运行时的动态链接而起作用的。您可能会想,“但我使用的是Swift,这与Objective-C有什么关系?”答案在于
#selector
机制。选择器基本上只是一个符号,Objective-C运行时在表中查找该符号以获取它(为您)调用的方法。这就是为什么在执行类似于
myObjectInstance.someMethod()
的操作时说“调用方法”在技术上是不正确的。正确的表达方式是向对象“发送消息”,因为这是运行时发生的事情。目标行动机制是围绕这一点建立的。
sendAction(u:Selector?,to:Any?)
方法执行相同的操作。因此,实际上您的代码执行以下操作:

  • 获取与
    URLSessionTask
    suspend()
    方法相对应的符号
  • 告诉
    UIApplication
    shared
    实例调用该符号的方法
  • 现在,这通常会导致崩溃,出现典型的“未知选择器发送到实例…”错误消息。但是在这里,毫无疑问,UIApplication也有一个用于该实例的方法(或者更确切地说,运行时也有一个用于该符号的方法列在表中)。您似乎“找到”了一个未在其公共头中声明的方法。您成功地规避了编译时检查,并调用了作为私有API一部分的方法。这在法律中是明确禁止的


    除此之外,我强烈建议不要一开始就试图以这种方式设计应用程序。正如maddy指出的,它也可能被认为违反了HIGs。即使你没有试图做任何恶意的事情,并且在你的应用程序描述中正确地解释了这一特性,苹果也不会放任不管(我想)。就我个人而言,作为一个用户,如果应用程序做了一些事情,系统已经有了一个不同的机制,至少在应用程序进入后台和前台方面,我也会觉得很烦人

    我不认为没有用户交互就可以做到这一点

    选项是您可以生成推送通知,告诉用户将应用程序带到前台

    当操作系统发送推送通知且目标应用程序未在前台运行时,它将显示该通知


    如果存在通知警报,并且用户点击或单击操作按钮(或移动操作滑块),则应用程序将启动并调用一个方法以传递本地通知对象或远程通知负载

    关闭/打开应用程序应由用户明确完成。苹果不支持任何其他关闭或打开应用的方式,上传到应用商店时将被拒绝。iOS人机界面指南规定:

    不要以编程方式退出

    永远不要退出iOS应用程序 因为人们倾向于将其解释为崩溃。 但是,如果外部环境阻止您的应用程序 按照预期运行,您需要告诉用户 并解释他们能做些什么。取决于如何 如果应用程序故障严重,您有两种选择

    *展示 一个有吸引力的屏幕,描述问题并建议 校正屏幕提供反馈,让用户放心 你的申请没有问题。它将用户置于控制之下, 让他们决定是否要采取纠正措施,并 继续使用应用程序或按Home(主页)按钮并打开 不同应用

    *如果应用程序的某些功能是 不工作,disp