iOS 神奇漏洞,教你如何让 App 图标「动」起来!

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

前几天写了一篇关于如何无缝切换 App Logo 无需系统弹窗的技术文章,感兴趣可以先看看,这篇文章是基于上一篇的。

本篇文章以之前文章为基础,如果还没看过的可以先看之前文章。

为应用配置多 Logo

轻松更换 App 图标,无需系统弹窗!

iOS 漏洞

自从 iOS 10.3 苹果允许开发人员为应用提供替代图标以来,已经有几年时间了,开发者可以配置不同图标供用户选择,相关技术文章可以看我之前发的。

然而,这个功能还比较基础只能在用户点击时设置,而且会有一个系统的弹窗,如果不想有这个弹窗,也可以看上次发的文章,通过一些"手段"来禁止这个弹窗弹出。

目前,除了苹果自带的应用(如时钟和日历)外,没有任何动画或交互式图标------但最近,有研究人员发现了一个可以做动画的漏洞,今天就来讲讲这方面的内容。

后台执行更换图标操作

我们知道设置其他图标是通过 UIApplication.shared .setAlternateIconName 这个 API 进行的,但是这个 API 有一些限制,首先,每次执行之后,都会有一个系统弹窗,经过一些探索,上一篇文章中已经成功跳过了这个限制。

下一个限制是这个 API 无法在后台执行,如果在后台执行就会报错,经过一些探索,系统底层调用的其实是一个名为 LSApplicationProxy 的类,通过调用 LSBundleProxybundleProxyForCurrentProcess 函数来创建了一个可以设置 App Logo 的实例。那么我们为了能够调用这个私有 API,先创建出这两个类的声明:

创建 LSApplicationProxy.h 文件:

objectivec 复制代码
#import <Foundation/Foundation.h>

@interface LSApplicationProxy: NSObject

- (void)setAlternateIconName:(nullable NSString *)name
                  withResult:(void (^_Nonnull)(BOOL success, NSError *_Nullable))result;

@end

创建 LSApplicationProxy.h 文件:

objectivec 复制代码
#import <Foundation/Foundation.h>

@interface LSBundleProxy: NSObject

+ (nonnull LSApplicationProxy *)bundleProxyForCurrentProcess;

@end

然后,在你的应用中创建 LSApplicationProxy 实例:

ini 复制代码
let appProxy: LSApplicationProxy = LSBundleProxy.bundleProxyForCurrentProcess()

在需要替换 App Logo 的地方执行替换方法即可:

lua 复制代码
self.appProxy.setAlternateIconName(selectName) { isSuccess, error  in
    if let error {
        print("设置 App Icon 出错: \(error)")
    } else {
        print("App Icon 设置成功")
    }
}

执行这个方法时,你会发现前台没问题,但是退到后台之后偶尔就无法执行了,为了在后台能够成功替换,我们需要创建一个后台任务,告诉系统,我们需要在后台执行一些代码:

objectivec 复制代码
UIApplication.shared.beginBackgroundTask()

这样代码放到 setAlternateIconName 之前即可。

另外,如果你的代码编译报错,提示无法找到 LSBundleProxy,我们需要告诉编译器我们代码中有这个类,导航到 Build Settings 中,在 Other Linker Flags 中增加:

bash 复制代码
-Wl,-U,_OBJC_CLASS_$_LSBundleProxy

然后运行项目,点击替换 App,然后退到后台,Logo 成功被替换:

让你的 App 图标动起来

既然能够在后台更换图标了,我们想要让图标动起来。简单的方法只需要将一个动画的每一帧做成一张 logo 图片,然后用一个定时器单位时间调用一次修改方法即可。

我这准备了几张 logo,然后 0.5 秒更换一张图片,简单演示一下:

swift 复制代码
class AnimateViewController: UIViewController {
    
    let iconNames = ["AppLogo 0", "AppLogo 1", "AppLogo 2", "AppLogo 3", "AppLogo 4"]
    
    var index = 0
    
    private let appProxy: LSApplicationProxy = LSBundleProxy.bundleProxyForCurrentProcess()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .white

        let button = UIButton(type: .system)
        button.setTitle("开始 Logo 动画", for: .normal)
        button.sizeToFit()
        button.addTarget(self, action: #selector(startAnimation), for: .touchUpInside)
        view.addSubview(button)
        button.center = view.center
    }
    
    @objc
    func startAnimation() {
        UIApplication.shared.beginBackgroundTask()
        Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { _ in
            self.appProxy.setAlternateIconName(self.getLogoName()) { isSuccess, error  in
                if let error {
                    print("设置 App Icon 出错: \(error)")
                } else {
                    print("App Icon 设置成功")
                }
            }
        }
    }
    
    func getLogoName() -> String {
        self.index += 1
        let i = index % 5
        return "AppLogo \(i)"
    }

}

最终效果:

动图不太清楚,可以前往我的视频号查看录屏。

这里每天分享一个 iOS 的新知识,快来关注我吧

本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
咕噜企业签名分发-淼淼3 小时前
开发源码搭建一码双端应用分发平台教程:逐步分析注意事项
android·ios
键盘敲没电13 小时前
【IOS】GCD学习
学习·ios·objective-c·xcode
SY.ZHOU13 小时前
Significant Location Change
macos·ios·cocoa
吴Wu涛涛涛涛涛Tao21 小时前
深入理解 Swift Codable:从基础到进阶
ios
大熊猫侯佩1 天前
由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(三)
数据库·swiftui·swift
大熊猫侯佩1 天前
由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(二)
数据库·swiftui·swift
大熊猫侯佩1 天前
用异步序列优雅的监听 SwiftData 2.0 中历史追踪记录(History Trace)的变化
数据库·swiftui·swift
大熊猫侯佩1 天前
由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(一)
数据库·swiftui·swift
Jouzzy1 天前
【iOS安全】iPhone X iOS 16.7.11 (20H360) WinRa1n 越狱教程
安全·ios·iphone
二流小码农2 天前
鸿蒙开发:实现一个标题栏吸顶
android·ios·harmonyos