【问题标题】:Put app on foreground programmatically on Swift在 Swift 中以编程方式将应用程序置于前台
【发布时间】:2019-03-08 02:48:00
【问题描述】:

我测试过:

UIControl().sendAction(#selector(URLSessionTask.suspend), to: UIApplication.shared, for: nil)

这是用于将应用程序置于后台并且它可以工作。

如何将应用重新置于前台?

我试过了:

UIControl().sendAction(#selector(URLSessionTask.resume), to: UIApplication.shared, for: nil)

但最终它崩溃了......

谢谢

【问题讨论】:

  • 这是一个有趣的技巧,可以在 UIApplication 上调用私有 suspend 方法。当然,如果 Apple 意识到您正在这样做,您的应用可能会被拒绝。
  • 真的吗?即使该应用程序是为此而设计的? (应用程序不会隐藏任何东西......)。无论如何,有没有办法做到这一点?
  • 作为用户,我希望不会,这会非常烦人
  • 您不能以编程方式将应用程序移至前台,这是不允许的。您可以执行诸如深度链接/通用链接之类的操作,但这一切都应该由用户发起。
  • 要实现的另一件事是,您的代码会暂停您的应用程序,而不仅仅是将其置于后台。一旦你的应用程序被挂起,它就不再运行,因此它不能将自己置于前台。您需要一个外部触发器,例如某种通知。

标签: ios swift foreground


【解决方案1】:

更新:

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

创建一个.h 文件并设置LSApplicationWorkspace 类的接口并列出所需的方法。您需要在桥接头中使用#import "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)
}

原文:

你所做的很可能违反了iOS Human Interface Guidelines(虽然“不要以编程方式退出”不再具体定义),所以正如cmets所说,它不适合App Store。无论如何,一旦您的应用程序以这种方式暂停,我不希望有办法以编程方式恢复它,除非您可以连接到 Background Operation 以运行 URLSessionTask.resume,但我还没有测试它并且不确定能不能用。

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

总而言之,我认为您最好的选择是尝试使用通知。这只是意味着用户需要点击通知才能将您的应用重新置于前台。

【讨论】:

  • 该应用程序就是为此而设计的...我知道它有点违反准则,但不是一个烦人的应用程序。在应用程序引用会这样说。问题是,如何?我尝试使用方案、URLSessionTask.resume(崩溃)但没有任何效果。
  • 它不仅“有点”违反了 iOS HIG,而且肯定违反了Apple Developer Program License Agreement。所以再次强调这一点:没有办法您将能够通过 AppStore 使用您在代码中进行的调用来销售它。我并不是说这是刻薄的,只是为了使您免于将精力投入到您将无法发布的内容上。如果它只是一个宠物项目,祝你好运! :)
  • Amg91,我已经用一个私有 API 示例更新了我的答案,该示例应该可以满足您的需求。
  • @JordanJohnson 嘿,这实际上是一个不错的发现。 :) 再次强调:这是 another 应用程序将原始应用程序带回前台的代码。属于目标应用程序的代码如果被挂起显然不能“让自己恢复活力”(并且 OP 的代码确实 suspend 它)。暂停的应用程序不执行任何操作,因此“恢复代码”也不会执行。此外:这基本上会切换应用程序,但如果您计划在后台执行它,您将无法使用任意计时器(因为后台应用程序最终也会暂停,这会停止所有计时器)。
  • 你是完全正确的 Gero。我假设他会尝试从某种Background Operation 中调用它。 Amg91 没有概述应用程序何时回到前台的确切“触发器”,所以我假设它在他选择的任何后台操作的约束范围内。 Amg91,只是为了确认。您的上述暂停应用程序的方法是否仍然允许后台操作?
【解决方案2】:

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

不要以编程方式退出

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

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

*如果您的应用程序只有部分功能是 不工作,当人们激活时显示屏幕或警报 该功能。仅当人们尝试访问时才显示警报 功能失效

【讨论】:

【解决方案3】:

作为对 Jordan 出色回答的后续行动,我想解释一下为什么您的代码首先可以工作,以及为什么仅此一项就会让您的应用被拒绝,即使没有任何功能可以使其再次处于活动状态并将其带到前景。

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

  1. 获取URLSessionTasksuspend()方法对应的符号。
  2. 告诉UIApplicationshared 实例调用it 对该符号的方法。

现在通常这会导致崩溃,并出现典型的“发送到实例的未知选择器...”错误消息。但是在这里,肯定是巧合UIApplication 有一个用于该实例的方法(或者更确切地说,运行时也有其表中列出的该符号的方法之一)。您有点“找到”了一个未在其公共标头中声明的方法。您成功地绕过了对此的编译时检查,并调用了作为 私有 API 一部分的方法。这是在Apple Developer Program License Agreement 中明确禁止的

除此之外,我强烈建议不要一开始就尝试以这种方式设计应用程序。正如 maddy 指出的那样,它也可能被认为违反了 HIG。即使您没有尝试做任何恶意并在您的应用程序描述中正确解释该功能,也不会让 Apple 让它滑动(我假设)。就个人而言,作为用户,如果应用程序以不同的方式执行系统已经具有特定机制的操作,至少在应用程序进入后台和前台方面,我也会觉得很烦人。

【讨论】:

  • 好的,所以你们是说这在技术上是不可能的?我知道许可协议和所有这些,如果可能的话,事情会更多,以及如何做到这一点。
  • 技术上这是可能的,正如乔丹在他的回答中所解释的那样。正如我所说,我只是想详细说明它是如何工作的,以及您成功将其提交到 AppStore 的机会的后果是什么。
【解决方案4】:

我认为没有用户交互就无法完成

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

当操作系统传递推送通知并且目标应用程序没有在前台运行时,它会呈现通知。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-26
    • 2016-04-21
    • 2020-08-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    相关资源
    最近更新 更多