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新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
2401_8658548815 小时前
iOS应用想要下载到手机上只能苹果签名吗?
后端·ios·iphone
HackerTom1 天前
iOS用rime且导入自制输入方案
ios·iphone·rime
良技漫谈1 天前
Rust移动开发:Rust在iOS端集成使用介绍
后端·程序人生·ios·rust·objective-c·swift
2401_852403551 天前
高效管理iPhone存储:苹果手机怎么删除相似照片
ios·智能手机·iphone
星际码仔2 天前
【动画图解】是怎样的方法,能被称作是 Flutter Widget 系统的核心?
android·flutter·ios
emperinter2 天前
WordCloudStudio:AI生成模版为您的文字云创意赋能 !
图像处理·人工智能·macos·ios·信息可视化·iphone
关键帧Keyframe2 天前
音视频面试题集锦第 7 期
音视频开发·视频编码·客户端
关键帧Keyframe2 天前
音视频面试题集锦第 8 期
ios·音视频开发·客户端
pb82 天前
引入最新fluwx2.5.4的时候报错
flutter·ios
KeithTsui2 天前
ZFC in LEAN 之 前集的等价关系(Equivalence on Pre-set)详解
开发语言·其他·算法·binder·swift