当前位置: 首页 > news >正文

iOS - 解压ipa包中的Assert.car文件

项目在 Archive 打包后,生成ipa
在这里插入图片描述
xxx.ipa文件修改为zip后缀即 xxx.zip ,然后再双击解压,会生成一个 Payload 文件夹,里面一个文件 如下图:
在这里插入图片描述

然后显示改文件的包内容:
在这里插入图片描述
在这里插入图片描述

解压 Assets.car 文件的方式:

方法一、 插件 AssetCatalogTinkerer

下载插件 AssetCatalogTinkerer ,用【My Mac】模拟器运行,然后 Assets.car 使用 AssetCatalogTinkerer 打开 ,如下图:
在这里插入图片描述
可以选择到处一张图片,也可选择到处所有图片:
在这里插入图片描述

方式二、插件 cartool

下载插件 cartool ,用【My Mac】模拟器运行,这时候会报错,替换main.m文件内容,如下:

//
//  main.m
//  cartool
//
//  Created by Steven Troughton-Smith on 14/07/2013.
//  Copyright (c) 2013 High Caffeine Content. All rights reserved.
//#import <Foundation/Foundation.h>
#import <ImageIO/ImageIO.h>typedef enum _kCoreThemeIdiom {kCoreThemeIdiomUniversal,kCoreThemeIdiomPhone,kCoreThemeIdiomPad,kCoreThemeIdiomTV,kCoreThemeIdiomCar,kCoreThemeIdiomWatch,kCoreThemeIdiomMarketing
} kCoreThemeIdiom;typedef NS_ENUM(NSInteger, UIUserInterfaceSizeClass) {UIUserInterfaceSizeClassUnspecified = 0,UIUserInterfaceSizeClassCompact     = 1,UIUserInterfaceSizeClassRegular     = 2,
};@interface CUICommonAssetStorage : NSObject-(NSArray *)allAssetKeys;
-(NSArray *)allRenditionNames;-(id)initWithPath:(NSString *)p;-(NSString *)versionString;@end@interface CUINamedImage : NSObject@property(readonly) CGSize size;
@property(readonly) CGFloat scale;
@property(readonly) kCoreThemeIdiom idiom;
@property(readonly) UIUserInterfaceSizeClass sizeClassHorizontal;
@property(readonly) UIUserInterfaceSizeClass sizeClassVertical;-(CGImageRef)image;@end@interface CUIRenditionKey : NSObject
@end@interface CUIThemeFacet : NSObject+(CUIThemeFacet *)themeWithContentsOfURL:(NSURL *)u error:(NSError **)e;@end@interface CUICatalog : NSObject@property(readonly) bool isVectorBased;-(id)initWithURL:(NSURL *)URL error:(NSError **)error;
-(id)initWithName:(NSString *)n fromBundle:(NSBundle *)b;
-(id)allKeys;
-(id)allImageNames;
-(CUINamedImage *)imageWithName:(NSString *)n scaleFactor:(CGFloat)s;
-(CUINamedImage *)imageWithName:(NSString *)n scaleFactor:(CGFloat)s deviceIdiom:(int)idiom;
-(NSArray *)imagesWithName:(NSString *)n;@endvoid CGImageWriteToFile(CGImageRef image, NSString *path)
{CFURLRef url = (__bridge CFURLRef)[NSURL fileURLWithPath:path];CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL);CGImageDestinationAddImage(destination, image, nil);if (!CGImageDestinationFinalize(destination)) {NSLog(@"Failed to write image to %@", path);}CFRelease(destination);
}NSString *idiomSuffixForCoreThemeIdiom(kCoreThemeIdiom idiom)
{switch (idiom) {case kCoreThemeIdiomUniversal:return @"";break;case kCoreThemeIdiomPhone:return @"~iphone";break;case kCoreThemeIdiomPad:return @"~ipad";break;case kCoreThemeIdiomTV:return @"~tv";break;case kCoreThemeIdiomCar:return @"~carplay";break;case kCoreThemeIdiomWatch:return @"~watch";break;case kCoreThemeIdiomMarketing:return @"~marketing";break;default:break;}return @"";
}NSString *sizeClassSuffixForSizeClass(UIUserInterfaceSizeClass sizeClass)
{switch (sizeClass){case UIUserInterfaceSizeClassCompact:return @"C";break;case UIUserInterfaceSizeClassRegular:return @"R";break;default:return @"A";}
}NSMutableArray *getImagesArray(CUICatalog *catalog, NSString *key)
{NSMutableArray *images = [[NSMutableArray alloc] initWithCapacity:5];for (NSNumber *scaleFactor in @[@1, @2, @3]){CUINamedImage *image = [catalog imageWithName:key scaleFactor:scaleFactor.doubleValue];if (image && image.scale == scaleFactor.floatValue) [images addObject:image];}return images;
}void exportCarFileAtPath(NSString * carPath, NSString *outputDirectoryPath)
{NSError *error = nil;outputDirectoryPath = [outputDirectoryPath stringByExpandingTildeInPath];//	CUIThemeFacet *facet = [CUIThemeFacet themeWithContentsOfURL:[NSURL fileURLWithPath:carPath] error:&error];
//
//	CUICatalog *catalog = [[CUICatalog alloc] init];// 替换成以下代码CUICatalog *catalog = nil;if ([CUICatalog instancesRespondToSelector:@selector(initWithURL:error:)]) {/* If CUICatalog has the URL API (Mojave), use it. */catalog = [[CUICatalog alloc] initWithURL:[NSURL fileURLWithPath:carPath] error:&error];} else {CUIThemeFacet *facet = [CUIThemeFacet themeWithContentsOfURL:[NSURL fileURLWithPath:carPath] error:&error];catalog = [[CUICatalog alloc] init];/* Override CUICatalog to point to a file rather than a bundle */[catalog setValue:facet forKey:@"_storageRef"];}/* Override CUICatalog to point to a file rather than a bundle */
//	[catalog setValue:facet forKey:@"_storageRef"];/* CUICommonAssetStorage won't link */CUICommonAssetStorage *storage = [[NSClassFromString(@"CUICommonAssetStorage") alloc] initWithPath:carPath];for (NSString *key in [storage allRenditionNames]){printf("%s\n", [key UTF8String]);NSArray* pathComponents = [key pathComponents];if (pathComponents.count > 1){// Create subdirectories for namespaced assets (those with names like "some/namespace/image-name")NSArray* subdirectoryComponents = [pathComponents subarrayWithRange:NSMakeRange(0, pathComponents.count - 1)];NSString* subdirectoryPath = [outputDirectoryPath copy];for (NSString* pathComponent in subdirectoryComponents){subdirectoryPath = [subdirectoryPath stringByAppendingPathComponent:pathComponent];}[[NSFileManager defaultManager] createDirectoryAtPath:subdirectoryPathwithIntermediateDirectories:YESattributes:nilerror:&error];}NSMutableArray *images = getImagesArray(catalog, key);for( CUINamedImage *image in images ){if( CGSizeEqualToSize(image.size, CGSizeZero) )printf("\tnil image?\n");else{CGImageRef cgImage = [image image];NSString *idiomSuffix = idiomSuffixForCoreThemeIdiom(image.idiom);NSString *sizeClassSuffix = @"";if (image.sizeClassHorizontal || image.sizeClassVertical){sizeClassSuffix = [NSString stringWithFormat:@"-%@x%@", sizeClassSuffixForSizeClass(image.sizeClassHorizontal), sizeClassSuffixForSizeClass(image.sizeClassVertical)];}NSString *scale = image.scale > 1.0 ? [NSString stringWithFormat:@"@%dx", (int)floor(image.scale)] : @"";NSString *name = [NSString stringWithFormat:@"%@%@%@%@.png", key, idiomSuffix, sizeClassSuffix, scale];printf("\t%s\n", [name UTF8String]);if( outputDirectoryPath )CGImageWriteToFile(cgImage, [outputDirectoryPath stringByAppendingPathComponent:name]);}}}
}int main(int argc, const char * argv[])
{@autoreleasepool {if (argc < 2){printf("Usage: cartool <path to Assets.car> [outputDirectory]\n");return -1;}exportCarFileAtPath([NSString stringWithUTF8String:argv[1]], argc > 2 ? [NSString stringWithUTF8String:argv[2]] : nil);}return 0;
}

然后修改 Edit Scheme ,如下:
在这里插入图片描述

在这里插入图片描述
设置好两个路径:
1.Assert.car文件的路径,我是放在桌面的上的,所以路径为:

/Users/xxx/Desktop/Assets.car

2.解压后的资源存在的路径,这里是一个文件夹路径,我是在桌面创建一个名为img的文件夹,所以路径为:

/Users/xxx/Desktop/img

替换完main.m文件,设置好路径后就可以运行该项目,然后可以看到控制台一直在输出内容,解压完成后,可以查看 img 文件夹里面解压后的资源图片 :
在这里插入图片描述
我们项目中是用的是 pdf 矢量图,所以打包后会自动生成 @1x、@2x、@3x图片,已适配不同分辨率的机型。

相关文章:

iOS - 解压ipa包中的Assert.car文件

项目在 Archive 打包后&#xff0c;生成ipa包 将 xxx.ipa文件修改为zip后缀即 xxx.zip &#xff0c;然后再双击解压&#xff0c;会生成一个 Payload 文件夹&#xff0c;里面一个文件 如下图&#xff1a; 然后显示改文件的包内容&#xff1a; 解压 Assets.car 文件的方式&…...

【Jmeter】配置不同业务请求比例,应对综合场景压测

目录 前言 Jmeter5.0新特性 核心改进 其他变化 资料获取方法 前言 Jmeter 5.0这次的核心改进是在许多地方改进了对 Rest 的支持&#xff0c;此外还有调试功能、录制功能的增强、报告的改进等。 我也是因为迁移到了Mac&#xff0c;准备在Mac上安装Jmeter的时候发现它已经…...

TCP拥塞控制详解 | 1. 概述

网络传输问题本质上是对网络资源的共享和复用问题&#xff0c;因此拥塞控制是网络工程领域的核心问题之一&#xff0c;并且随着互联网和数据中心流量的爆炸式增长&#xff0c;相关算法和机制出现了很多创新&#xff0c;本系列是免费电子书《TCP Congestion Control: A Systems …...

使用IPSEC VPN 在有防火墙的场景和有NAT转换的场景下实现隧道通信实验

目录 一、在有防火墙的场景 1、为所有设备配置对应ip地址&#xff1a; 2、进入两个防火墙实现公网互通 3、测试公网是否互通 4、进入SW1配置IPSEC VPN 5、进入SW2配置IPSEC VPN 6、配置策略方向ESP的流量 7、尝试使用PC1访问PC2 二、在有NAT地址转换的场景 1、为新增加…...

Go和Java实现适配器模式

Go和Java实现适配器模式 我们通过下面的实例来演示适配器模式的使用&#xff0c;其中&#xff0c;音频播放器设备只能播放 mp3 文件&#xff0c;通过使用一个更高级 的音频播放器来播放 vlc 和 mp4 文件。 1、适配器模式 适配器模式是作为两个不兼容的接口之间的桥梁。这种…...

接口相似数据结构复用率高?Apipost这招搞定!

在API设计和开发过程中&#xff0c;存在许多瓶颈&#xff0c;其中一个主要问题是在遇到相似数据结构的API时会产生重复性较多的工作&#xff1a;在每个API中都编写相同的数据&#xff0c;这不仅浪费时间和精力&#xff0c;还容易出错并降低API的可维护性。 为了解决这个问题&a…...

【零基础学Rust | 基础系列 | Hello, Rust】编写并运行第一个Rust程序

文章目录 前言一&#xff0c;创建项目二&#xff0c;两种编译方式1. 使用rustc编译器编译2. 使用Cargo编译 总结 前言 在开始学习任何一门新的编程语言时&#xff0c;都会从编写一个简单的 “Hello, World!” 程序开始。在这一章节中&#xff0c;将会介绍如何在Rust中编写并运…...

代理模式.

前言&#xff1a; 为什么要学习代理模式&#xff0c;因为AOP的底层机制就是动态代理&#xff01; 代理模式&#xff1a; 静态代理 动态代理 静态代理 抽象角色 : 一般使用接口或者抽象类来实现 真实角色 : 被代理的角色 代理角色 : 代理真实角色 ; 代理真实角色后 , 一…...

BS框架说明

B/S架构 1.B/S框架&#xff0c;意思是前端&#xff08;Browser 浏览器&#xff0c;小程序、app、自己写的&#xff09;和服务器端&#xff08;Server&#xff09;组成的系统的框架结构 2.B/S框架&#xff0c;也可理解为web架构&#xff0c;包含前端、后端、数据库三大组成部分…...

iOS——Block签名

首先来看block结构体对象Block_layout&#xff08;等同于clang编译出来的__Block_byref_a_0&#xff09; #define BLOCK_DESCRIPTOR_1 1 struct Block_descriptor_1 {uintptr_t reserved;uintptr_t size; };#define BLOCK_DESCRIPTOR_2 1 struct Block_descriptor_2 {// requi…...

Flutter 图片选取及裁剪

在开发项目里修改用户头像的功能&#xff0c;涉及到图片选取及裁剪&#xff0c;基本实现步骤如下&#xff1a; 1、pubspec.yaml 添加 image_picker: ^1.0.1 image_cropper: ^4.0.1&#xff1a; dependencies:image_picker: ^1.0.1image_cropper: ^4.0.1flutter:sdk: flutter…...

C语言每日一题:11.《数据结构》链表分割。

题目一&#xff1a; 题目链接&#xff1a; 思路一&#xff1a;使用带头链表 1.构建两个新的带头链表&#xff0c;头节点不存储数据。 2.循环遍历原来的链表。 3.小于x的尾插到第一个链表。 4.大于等于x尾插到第二个链表。 5.进行链表合并&#xff0c;注意第二个链表的尾的下一…...

记一次Oracle归档日志异常增长问题的排查过程

Oracle归档日志是Oracle数据库的重要功能&#xff0c;用于将数据库的重做日志文件&#xff08;Redo Log&#xff09;保存到归档日志文件&#xff08;Archive Log&#xff09;中。归档日志的作用是提供数据库的备份和恢复功能&#xff0c;以及支持数据库的持续性和数据完整性。 …...

Java设计模式——类之间的关系

1.继承关系(泛化) 类与子类的关系&#xff0c;指一个类继承另外的一个类。 2.实现关系 一个类可以实现多个接口&#xff0c;实现所有接口的功能。 3.依赖关系 类B作为类A方法中的局部变量或者参数出现&#xff0c;表示A依赖B。 4.关联关系 类B作为类A中的成员变量出现&#…...

Dockerfile构建Redis镜像

建立工作目录 [rootlocalhost ~]# mkdir redis [rootlocalhost ~]# cd redis/ 编写Dockerfile文件 [rootlocalhost redis]# vim Dockerfile FROM centos:7 MAINTAINER dddd <dddd163.com> RUN yum -y install epel-release && yum -y install redis RUN sed -i …...

C高级DAY2

1.思维导图 2. 递归实现&#xff0c;输入一个数&#xff0c;输出这个数的每一位 递归实现&#xff0c;输入一个数&#xff0c;输出这个数的二进制c 写一个脚本&#xff0c;包含以下内容&#xff1a; 显示/etc/group文件中第五行的内容创建目录/home/ubuntu/copy切换工作路径到…...

Linux 服务管理

在Linux上&#xff0c;服务管理是指对系统中运行的服务进行启动、停止、重启、监控和配置的过程。以下是一些常用的Linux服务管理工具和命令&#xff1a; 1. systemctl&#xff1a;systemctl 是一个Linux系统服务管理工具&#xff0c;可以管理Systemd初始化系统的服务。常见的…...

问题记录 1 页面初始化触发el-form必填校验

bug: 先编辑table某条数据,然后关闭,再去新增的时候就会触发el-form必填校验, 网上搜了一下是因为 rules里触发的方式为change时,赋值数据的格式不一致导致触发校验, 最后也没找到正确的解决方法, 只能用很low方式去解决了 方案1. 把trigger改为 blur 失焦后触发 方案2. 初始化…...

后端整理(JVM、Redis、反射)

1. JVM 文章仅为自身笔记 详情查看一篇文章掌握整个JVM&#xff0c;JVM超详细解析&#xff01;&#xff01;&#xff01; 1.1 什么是JVM jvm是Java虚拟机 1.2 Java文件的编译过程 程序员编写代码形成.java文件经过javac编译成.class文件再通过JVM的类加载器进入运行时数据…...

1. CUDA中的grid和block

1. CUDA中的grid和block基本的理解 Kernel: Kernel不是CPU&#xff0c;而是在GPU上运行的特殊函数。你可以把Kernel想象成GPU上并行执行的任务。当你从主机&#xff08;CPU&#xff09;调用Kernel时&#xff0c;它在GPU上启动&#xff0c;并在许多线程上并行运行。 Grid: 当你…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...