前言砸壳网站 https://decrypt.day/ 广告太多，而且砸完的 APP 经常不能用。本文介绍如何使用flexdecrypt工具对iOS应用进行砸壳（解密），获取可用于逆向分析的IPA文件。注意Clutch 已经不能用了，现在一般使用 flexdecrypt 来砸壳。开始工具下载1. FlexdecryptGitHub仓库: https://github.com/JohnCoates/flexdecrypt直接下载:# 下载预编译版本 wget https://github.com/JohnCoates/flexdecrypt/releases/download/1.1/flexdecrypt.deb # 或下载二进制文件 wget https://github.com/JohnCoates/flexdecrypt/releases/download/1.1/flexdecrypt2. Flexdump辅助脚本Gist地址: https://gist.github.com/defparam/71d67ee738341559c35c684d659d40ac下载命令:curl -o flexdump https://gist.githubusercontent.com/defparam/71d67ee738341559c35c684d659d40ac/raw/flexdump3. 其他可选工具frida-ios-dump: https://github.com/AloneMonkey/frida-ios-dumpCrackerXI+: Cydia/Sileo商店安装安装步骤方法一：使用自动化脚本创建flexdecrypt_install.sh脚本：#!/bin/bash # 配置 IPHONE_IP="192.168.50.57" # 修改为你的iPhone IP IPHONE_USER="root" IPHONE_PASS="alpine" # 修改为你的root密码 # 下载flexdecrypt if [ ! -f flexdecrypt ]; then echo "Downloading flexdecrypt..." curl -L -o flexdecrypt https://github.com/JohnCoates/flexdecrypt/releases/download/1.1/flexdecrypt fi # 下载flexdump if [ ! -f flexdump ]; then echo "Downloading flexdump..." curl -o flexdump https://gist.githubusercontent.com/defparam/71d67ee738341559c35c684d659d40ac/raw/flexdump fi # 传输到iPhone echo "Transferring files to iPhone..." sshpass -p "$IPHONE_PASS" scp flexdecrypt root@$IPHONE_IP:/var/jb/usr/bin/ sshpass -p "$IPHONE_PASS" scp flexdump root@$IPHONE_IP:/var/jb/usr/bin/ # 设置权限 echo "Setting permissions..." sshpass -p "$IPHONE_PASS" ssh root@$IPHONE_IP "chmod +x /var/jb/usr/bin/flexdecrypt /var/jb/usr/bin/flexdump" # 创建符号链接（flexdump需要） sshpass -p "$IPHONE_PASS" ssh root@$IPHONE_IP "ln -sf /var/jb/usr/bin/flexdecrypt /var/jb/usr/bin/flexdecrypt2" echo "Installation complete!"方法二：手动安装连接到iPhone:ssh root@192.168.50.57 # 输入密码传输文件:# 在Mac上执行 scp flexdecrypt root@192.168.50.57:/var/jb/usr/bin/ scp flexdump root@192.168.50.57:/var/jb/usr/bin/设置权限:# 在iPhone上执行 chmod +x /var/jb/usr/bin/flexdecrypt chmod +x /var/jb/usr/bin/flexdump ln -s /var/jb/usr/bin/flexdecrypt /var/jb/usr/bin/flexdecrypt2使用方法1. 列出所有应用# 使用flexdump列出应用 ssh root@192.168.50.57 "/var/jb/usr/bin/flexdump list" # 手动列出应用 ssh root@192.168.50.57 "ls /var/containers/Bundle/Application/*/2. 砸壳指定应用使用flexdump（推荐）# 在iPhone上执行 /var/jb/usr/bin/flexdump dump AppName.app # 例如： /var/jb/usr/bin/flexdump dump WeChat.app /var/jb/usr/bin/flexdump dump DUApp.app直接使用flexdecrypt# 找到应用路径 cd /var/containers/Bundle/Application/[UUID]/AppName.app # 解密二进制文件 flexdecrypt AppName AppName_decrypted # 手动打包IPA（需要额外步骤）3. 下载砸壳后的IPA# IPA默认保存在 /var/root/dump/ scp root@192.168.50.57:/var/root/dump/AppName_*.ipa ~/Desktop/验证砸壳结果1. 检查文件大小砸壳后的IPA通常会比App Store版本小（去除了加密层）：ls -lh ~/Desktop/*.ipa2. 解压IPA检查# 解压IPA unzip -q AppName.ipa -d AppName_extracted # 检查二进制文件加密状态 cd AppName_extracted/Payload/AppName.app otool -l AppName | grep -A 4 LC_ENCRYPTION_INFO如果cryptid为0，表示已成功解密。3. 使用class-dump验证# 安装class-dump brew install class-dump # 导出头文件（只对Objective-C有效） class-dump -H AppName -o headers/4. 在IDA Pro/Hopper中打开成功砸壳的二进制文件可以直接在逆向工具中分析。参考资源Flexdecrypt GitHubiOS App Reverse EngineeringThe iPhone Wikir/jailbreak已测试应用应用名称Bundle Name版本IPA大小状态微信WeChat.app8.0.50198MB✅ 成功得物DUApp.app5.81.5127MB✅ 成功
前言Jaco 中大量用到了 pag 动画，今天我们就来盘一盘 pag 的源代码。libpag 地址在这里。目录结构大概是这样： libpag/ ├── src/ # 核心源代码 ├── include/ # 公共 API 头文件 ├── third_party/ # 第三方依赖 ├── test/ # 测试代码和资源 ├── resources/ # 测试资源文件 ├── web/ # Web 平台实现 ├── ios/ # iOS 平台项目 ├── android/ # Android 平台项目 ├── mac/ # macOS 平台项目 ├── ohos/ # OpenHarmony 平台项目 ├── linux/ # Linux 平台支持 ├── win/ # Windows 平台项目 ├── viewer/ # PAG 查看器应用 ├── exporter/ # After Effects 导出器 ├── vendor/ # 供应商特定代码 ├── tgfx/ # TGFX 图形库（符号链接） ├── assets/ # 项目资源文件 └── .github/ # GitHub 配置 具体功能：src/base/作用: 基础数据结构和动画元素定义keyframes/: 关键帧动画系统，处理各种属性的时间插值 shapes/: 矢量形状定义（椭圆、矩形、路径、星形等） text/: 文本渲染相关（字体、段落、文字样式） effects/: 视觉效果（模糊、发光、阴影等 AE 效果） layerStyles/: 图层样式（描边、填充、渐变等） utils/: 基础工具类（数学运算、矩阵变换、颜色处理）src/codec/作用: PAG 文件格式编解码tags/: PAG 文件标签解析器，每个标签对应一种数据类型 mp4/: MP4 容器格式支持，用于视频预合成 utils/: 编解码工具（数据流读写、压缩解压）src/rendering/作用: 渲染引擎核心 layers/: 各种图层类型的渲染实现 ShapeLayer: 矢量形状图层 TextLayer: 文本图层 ImageLayer: 图片图层 SolidLayer: 纯色图层 PreComposeLayer: 预合成图层 filters/: GPU 滤镜和特效处理 video/: 视频解码和播放 sequences/: 序列帧管理 graphics/: 图形绘制基础设施 caches/: 渲染缓存系统（纹理、路径、字形缓存） drawables/: 可绘制对象抽象 editing/: 运行时编辑功能 renderers/: 不同渲染器实现 utils/: 渲染工具类 src/platform/作用: 平台特定实现android/: Android NDK/JNI 绑定，硬件解码器接口 ios/: iOS 框架集成，Metal/OpenGL 支持 mac/: macOS 特定功能，视频工具箱集成 cocoa/: iOS/macOS 共享的 Objective-C++ 代码 web/: WebAssembly 绑定，Canvas/WebGL 接口 win/: Windows 平台支持，DirectX/ANGLE 集成 ohos/: OpenHarmony 平台适配 linux/: Linux 平台基础支持 qt/: Qt 框架集成（跨平台 GUI） swiftshader/: 软件渲染器支持 源代码很难跑起来，我们要想使用他的话，还是下一个针对 iOS 的 demo。地址在这里：https://github.com/libpag/pag-ios开始iOS 项目一览运行 Demo 后，我们可以看到如下页面：可以看到他的功能比较强大，我们只需要一个 pag 文件，然后代码中加载即可。参考pag 官网
前言从今天开始，我们出一个系列叫做拆包达人：通过对 IPA 包的拆解，逆向的方式来学习，废话不多说，现在开始。Jaco中东直播应用，对标 TikTok 或者抖音，其 APP 长这样：拆完 IPA 包后，我们看到目录如下：. ├── _CodeSignature │ └── CodeResources ├── ai_generating.pag ├── ai_preparing.pag ├── AliVideoCert-com_weo_projectz-20240418175247.crt ├── AppAuthCore_Privacy.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── AppsFlyerLib_Privacy.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── ar.lproj │ ├── AppLocalizable.strings │ ├── InfoPlist.strings │ ├── JacoLocalizable.strings │ ├── LaunchScreen.strings │ ├── LiveLocalizable.strings │ ├── Localizable.strings │ ├── Main.strings │ ├── MessageLocalizable.strings │ ├── RongCloudKit.strings │ └── RongSticker.strings ├── Assets.car ├── AVPlayerPage.txt ├── Base.lproj │ ├── LaunchScreen.storyboardc │ └── Main.storyboardc ├── batter_full_like.json ├── batter_like_avatar.json ├── batter_like_heart.json ├── batter_like_soccer.json ├── BeetoADBundle.bundle │ ├── Assets.car │ ├── Info.plist │ └── zh-cn.lproj ├── big_playback_lottie.json ├── big_record_lottie.json ├── BMeiSheSDK.bundle │ ├── Info.plist │ └── meishe.lic ├── box_open.json ├── box_unclick.json ├── box_win.json ├── Bubble Tea.png ├── caption.bundle │ ├── 0C1A0ABB-3ECA-46B3-95C4-07555BBA3A5F.1.captionstyle │ ├── 0C1A0ABB-3ECA-46B3-95C4-07555BBA3A5F.lic │ ├── 0D4D1A68-5CE2-46E8-8635-7672EBA35FA2.1.captionstyle │ ├── 0D4D1A68-5CE2-46E8-8635-7672EBA35FA2.lic │ ├── 1C7EE477-20E9-494F-BF48-4D37E834A725.1.captionstyle │ ├── 1C7EE477-20E9-494F-BF48-4D37E834A725.lic │ ├── 1E61C62D-1317-4A5C-8773-830A19514735.1.captionstyle │ ├── 1E61C62D-1317-4A5C-8773-830A19514735.lic │ ├── 2044EE5C-D0B6-4E76-B6D5-391F0C4AD05E.1.captionstyle │ ├── 2044EE5C-D0B6-4E76-B6D5-391F0C4AD05E.lic │ ├── 24206D2B-F06E-4AA5-B4DF-5E103DF9DAB7.1.captionstyle │ ├── 24206D2B-F06E-4AA5-B4DF-5E103DF9DAB7.lic │ ├── 2C7609BE-7563-4E79-853D-B5540F593A11.1.captionstyle │ ├── 2C7609BE-7563-4E79-853D-B5540F593A11.lic │ ├── 2FE34C0F-F984-456F-8E2F-60EB1FEFEB90.9.captionstyle │ ├── 2FE34C0F-F984-456F-8E2F-60EB1FEFEB90.lic │ ├── 315FEA0F-A05B-4396-9C8D-2D3EDA001C81.1.captionstyle │ ├── 315FEA0F-A05B-4396-9C8D-2D3EDA001C81.lic │ ├── 39B0B7E1-D914-4AA6-BFBB-53123FA6607C.1.captionstyle │ ├── 39B0B7E1-D914-4AA6-BFBB-53123FA6607C.lic │ ├── 3A23D76E-4D68-4842-AE7E-DDC1CDE2B36C.1.captionstyle │ ├── 3A23D76E-4D68-4842-AE7E-DDC1CDE2B36C.lic │ ├── 3F23B70F-05B4-4108-B001-C3FB866DF72A.1.captionstyle │ ├── 3F23B70F-05B4-4108-B001-C3FB866DF72A.lic │ ├── 43B73C4F-0652-4EA4-952A-4204F678A47E.1.captionstyle │ ├── 43B73C4F-0652-4EA4-952A-4204F678A47E.lic │ ├── 49566C3C-D1E3-46C0-BFEC-BDB785530BAF.1.captionstyle │ ├── 49566C3C-D1E3-46C0-BFEC-BDB785530BAF.lic │ ├── 4A625662-8FC9-4033-A661-FBD3D2CF1FEA.1.captionstyle │ ├── 4A625662-8FC9-4033-A661-FBD3D2CF1FEA.lic │ ├── 4C76AACA-19AC-481F-AE1E-0F32625B2EC3.4.captionstyle │ ├── 4C76AACA-19AC-481F-AE1E-0F32625B2EC3.lic │ ├── 5726F064-1EB5-4D5A-8192-8B3949C0E4EA.1.captionstyle │ ├── 5726F064-1EB5-4D5A-8192-8B3949C0E4EA.lic │ ├── 5A0EFE09-AD94-4C01-9CC8-610D5873DEAE.1.captionstyle │ ├── 5A0EFE09-AD94-4C01-9CC8-610D5873DEAE.lic │ ├── 5BDEA66F-2326-4DFD-A7C5-75C75655CCC6.1.captionstyle │ ├── 5BDEA66F-2326-4DFD-A7C5-75C75655CCC6.lic │ ├── 656B18C0-8C65-4286-93C8-1690E5EE9E88.1.captionstyle │ ├── 656B18C0-8C65-4286-93C8-1690E5EE9E88.lic │ ├── 65A85DA8-E2A6-4408-9699-05AB791AD6B4.1.captionstyle │ ├── 65A85DA8-E2A6-4408-9699-05AB791AD6B4.lic │ ├── 66CBBEB8-FB1D-4DA3-B6E2-48DECEF95A07.1.captionstyle │ ├── 66CBBEB8-FB1D-4DA3-B6E2-48DECEF95A07.lic │ ├── 690C25D3-56FA-43F5-B7DD-5230EECF81DD.2.captionstyle │ ├── 690C25D3-56FA-43F5-B7DD-5230EECF81DD.lic │ ├── 73B20460-8228-4101-BE96-BCABE60F794D.1.captionstyle │ ├── 73B20460-8228-4101-BE96-BCABE60F794D.lic │ ├── 8027447F-73A1-4A64-8B13-4876E8F1567E.1.captionstyle │ ├── 8027447F-73A1-4A64-8B13-4876E8F1567E.lic │ ├── 82EFFD41-E686-4BA4-9BF6-74F648E0E3FB.1.captionstyle │ ├── 82EFFD41-E686-4BA4-9BF6-74F648E0E3FB.lic │ ├── 867C5CE6-849C-496F-9150-90E8B3B7D0AF.1.captionstyle │ ├── 867C5CE6-849C-496F-9150-90E8B3B7D0AF.lic │ ├── 916609BB-1B9A-40AA-9C87-596998DD2D0F.1.captionstyle │ ├── 916609BB-1B9A-40AA-9C87-596998DD2D0F.lic │ ├── 93338969-F0BE-457F-9E31-CFCB95F1F937.5.captionstyle │ ├── 93338969-F0BE-457F-9E31-CFCB95F1F937.lic │ ├── 96CE3810-928D-426D-84D8-1791641D5930.1.captionstyle │ ├── 96CE3810-928D-426D-84D8-1791641D5930.lic │ ├── 9C0ABC4C-6AA7-4394-95E8-50CC2DEF7191.1.captionstyle │ ├── 9C0ABC4C-6AA7-4394-95E8-50CC2DEF7191.lic │ ├── 9D252FC7-8587-418F-9BF8-974FF8593171.4.captionstyle │ ├── 9D252FC7-8587-418F-9BF8-974FF8593171.lic │ ├── A21DA7C1-4CA8-4A60-A764-78D036CAA18E.1.captionstyle │ ├── A21DA7C1-4CA8-4A60-A764-78D036CAA18E.lic │ ├── A983E9E2-CA00-45C1-9DB0-6204EABE2361.1.captionstyle │ ├── A983E9E2-CA00-45C1-9DB0-6204EABE2361.lic │ ├── B1CE8932-092A-421A-AF34-B43C61AB08EE.1.captionstyle │ ├── B1CE8932-092A-421A-AF34-B43C61AB08EE.lic │ ├── B3967436-19CF-4521-82E5-B607FDE87F68.1.captionstyle │ ├── B3967436-19CF-4521-82E5-B607FDE87F68.lic │ ├── B9B1C935-04F3-4CA0-B512-AB1450BC462F.1.captionstyle │ ├── B9B1C935-04F3-4CA0-B512-AB1450BC462F.lic │ ├── BB2B9917-C49E-4A4E-9722-C6ED1B35489A.1.captionstyle │ ├── BB2B9917-C49E-4A4E-9722-C6ED1B35489A.lic │ ├── BF688B3C-42C2-41A6-9EDB-DFB0A8D9393D.1.captionstyle │ ├── BF688B3C-42C2-41A6-9EDB-DFB0A8D9393D.lic │ ├── C0B02545-0233-4916-AB60-8A079373E9D8.1.captionstyle │ ├── C0B02545-0233-4916-AB60-8A079373E9D8.lic │ ├── C48AA6C4-486A-4101-A269-9689EFB529E7.1.captionstyle │ ├── C48AA6C4-486A-4101-A269-9689EFB529E7.lic │ ├── caption_style1.png │ ├── caption_style2.png │ ├── caption_style3.png │ ├── caption_style4.png │ ├── caption_style5.png │ ├── caption.json │ ├── D085861B-0A01-4D2B-A061-4DF4D8BBDDB2.2.captionstyle │ ├── D085861B-0A01-4D2B-A061-4DF4D8BBDDB2.lic │ ├── D3B7527A-811B-4098-AFBE-208F034C394D.1.captionstyle │ ├── D3B7527A-811B-4098-AFBE-208F034C394D.lic │ ├── D929CC52-C463-4042-89BD-F7686CD9851A.1.captionstyle │ ├── D929CC52-C463-4042-89BD-F7686CD9851A.lic │ ├── E06AC0E0-8C8E-4A81-A30C-C65839CEED91.1.captionstyle │ ├── E06AC0E0-8C8E-4A81-A30C-C65839CEED91.lic │ ├── EA8CB895-9EFC-48AB-9CFC-035A93CBF0FD.2.captionstyle │ ├── EA8CB895-9EFC-48AB-9CFC-035A93CBF0FD.lic │ ├── EADEB54E-411C-46AC-A88B-547D80DDDDBF.1.captionstyle │ ├── EADEB54E-411C-46AC-A88B-547D80DDDDBF.lic │ ├── EC2BBA40-981B-450F-A582-104187FAEC17.2.captionstyle │ └── EC2BBA40-981B-450F-A582-104187FAEC17.lic ├── capture_tip.gif ├── category.json ├── ComposeMakeup.bundle │ └── ComposeMakeup ├── cross_room.json ├── dark.json ├── Deep.png ├── DGCharts.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── dm_livecard_live.json ├── dm_voice_delete.json ├── dm_voice_lock_img.png ├── dm_voice_lock.json ├── doubleLike.json ├── doubleLikeSoccer.json ├── Emoji.plist ├── EmojiList.plist ├── en.lproj │ ├── AppLocalizable.strings │ ├── InfoPlist.strings │ ├── JacoLocalizable.strings │ ├── LaunchScreen.strings │ ├── LiveLocalizable.strings │ ├── Localizable.strings │ ├── Main.strings │ ├── MessageLocalizable.strings │ ├── RongCloudKit.strings │ └── RongSticker.strings ├── engaging.json ├── enter_live_arrow.pag ├── FBLPromises_Privacy.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── feed_voice_wave.json ├── filter.bundle │ ├── filter.json │ ├── mopian_6945244021867921415 │ ├── qingkong_6945244054134538270 │ ├── tongnian_6945244030104649736 │ └── Warmfood_7165158837891104769 ├── filters.json ├── FMDB_Privacy.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── Frameworks │ ├── AgoraAiEchoCancellationExtension.framework │ ├── AgoraAiNoiseSuppressionExtension.framework │ ├── Agorafdkaac.framework │ ├── Agoraffmpeg.framework │ ├── AgoraReplayKitExtension.framework │ ├── AgoraRtcKit.framework │ ├── AgoraSoundTouch.framework │ ├── AgoraVideoDecoderExtension.framework │ ├── AgoraVideoEncoderExtension.framework │ ├── alivcffmpeg.framework │ ├── AliyunMediaDownloader.framework │ ├── AliyunPlayer.framework │ ├── aosl.framework │ ├── IQKeyboardManagerSwift.framework │ ├── libpag.framework │ ├── NveEffectKit.framework │ ├── NvStreamingSdkCore.framework │ ├── RongChatRoom.framework │ ├── RongCustomerService.framework │ ├── RongDiscussion.framework │ ├── RongIMKit.framework │ ├── RongIMLib.framework │ ├── RongIMLibCore.framework │ ├── RongPublicService.framework │ ├── RongSight.framework │ ├── SCSDKCameraKit.framework │ ├── SCSDKCoreKit.framework │ ├── SCSDKCreativeKit.framework │ ├── Sentry.framework │ ├── tsr_client.framework │ ├── video_dec.framework │ ├── video_enc.framework │ └── ZegoExpressEngine.framework ├── GCDWebUploader.bundle │ └── Contents ├── gift_guidance_border.pag ├── gift_sound.mp3 ├── gold_coins_animation.json ├── GoogleCast.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── GoogleCastCoreResources.bundle │ ├── af.lproj │ ├── ar.lproj │ ├── bg.lproj │ ├── bn.lproj │ ├── ca.lproj │ ├── CastFrameworkDB.momd │ ├── cs.lproj │ ├── da.lproj │ ├── de.lproj │ ├── el.lproj │ ├── en_GB.lproj │ ├── en.lproj │ ├── es_419.lproj │ ├── es.lproj │ ├── et.lproj │ ├── fa.lproj │ ├── fi.lproj │ ├── fil.lproj │ ├── fr.lproj │ ├── hi.lproj │ ├── hr.lproj │ ├── hu.lproj │ ├── hy.lproj │ ├── Icons │ ├── id.lproj │ ├── is.lproj │ ├── it.lproj │ ├── iw.lproj │ ├── ja.lproj │ ├── ka.lproj │ ├── km.lproj │ ├── ko.lproj │ ├── lo.lproj │ ├── lt.lproj │ ├── lv.lproj │ ├── mk.lproj │ ├── mn.lproj │ ├── mr.lproj │ ├── ms.lproj │ ├── my.lproj │ ├── ne.lproj │ ├── nl.lproj │ ├── no.lproj │ ├── pl.lproj │ ├── pt_PT.lproj │ ├── pt.lproj │ ├── ro.lproj │ ├── ru.lproj │ ├── si.lproj │ ├── sk.lproj │ ├── sl.lproj │ ├── sr.lproj │ ├── sv.lproj │ ├── sw.lproj │ ├── ta.lproj │ ├── th.lproj │ ├── tr.lproj │ ├── uk.lproj │ ├── vi.lproj │ ├── zh_CN.lproj │ ├── zh_TW.lproj │ └── zh.lproj ├── GoogleCastUIResources.bundle │ ├── af.lproj │ ├── ar.lproj │ ├── Base.lproj │ ├── bg.lproj │ ├── bn.lproj │ ├── ca.lproj │ ├── cs.lproj │ ├── da.lproj │ ├── de.lproj │ ├── el.lproj │ ├── en_GB.lproj │ ├── en.lproj │ ├── es_419.lproj │ ├── es.lproj │ ├── et.lproj │ ├── fa.lproj │ ├── fi.lproj │ ├── fil.lproj │ ├── fr.lproj │ ├── hi.lproj │ ├── hr.lproj │ ├── hu.lproj │ ├── hy.lproj │ ├── Icons │ ├── id.lproj │ ├── is.lproj │ ├── it.lproj │ ├── iw.lproj │ ├── ja.lproj │ ├── ka.lproj │ ├── km.lproj │ ├── ko.lproj │ ├── lo.lproj │ ├── lt.lproj │ ├── lv.lproj │ ├── mk.lproj │ ├── mn.lproj │ ├── mr.lproj │ ├── ms.lproj │ ├── my.lproj │ ├── ne.lproj │ ├── nl.lproj │ ├── no.lproj │ ├── pl.lproj │ ├── pt_PT.lproj │ ├── pt.lproj │ ├── ro.lproj │ ├── ru.lproj │ ├── si.lproj │ ├── sk.lproj │ ├── sl.lproj │ ├── sr.lproj │ ├── sv.lproj │ ├── sw.lproj │ ├── ta.lproj │ ├── th.lproj │ ├── tr.lproj │ ├── uk.lproj │ ├── vi.lproj │ ├── zh_CN.lproj │ ├── zh_TW.lproj │ └── zh.lproj ├── GoogleService-Info.plist ├── GoogleSignIn.bundle │ ├── ar.lproj │ ├── ca.lproj │ ├── cs.lproj │ ├── da.lproj │ ├── de.lproj │ ├── el.lproj │ ├── en_GB.lproj │ ├── en.lproj │ ├── es_MX.lproj │ ├── es.lproj │ ├── fi.lproj │ ├── fr_CA.lproj │ ├── fr.lproj │ ├── google.png │ ├── google@2x.png │ ├── google@3x.png │ ├── he.lproj │ ├── hi.lproj │ ├── hr.lproj │ ├── hu.lproj │ ├── id.lproj │ ├── Info.plist │ ├── it.lproj │ ├── ja.lproj │ ├── ko.lproj │ ├── ms.lproj │ ├── nb.lproj │ ├── nl.lproj │ ├── pl.lproj │ ├── PrivacyInfo.xcprivacy │ ├── pt_BR.lproj │ ├── pt_PT.lproj │ ├── pt.lproj │ ├── ro.lproj │ ├── Roboto-Bold.ttf │ ├── ru.lproj │ ├── sk.lproj │ ├── sv.lproj │ ├── th.lproj │ ├── tr.lproj │ ├── uk.lproj │ ├── vi.lproj │ ├── zh_CN.lproj │ └── zh_TW.lproj ├── GoogleUtilities_Privacy.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── GTMAppAuth_Privacy.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── GTMSessionFetcher_Core_Privacy.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── home_interest_selection_guide.pag ├── icon_logo_new.png ├── Info.plist ├── InfoDebug.plist ├── JACO ├── Jaco Style.png ├── jaco_3_0_home_heart.pag ├── jaco_3_0_home_viewers.pag ├── jaco_3.0_support_coin.pag ├── jaco_3.0_support_flower.pag ├── jaco_profile_guide_side.pag ├── jaco_profile_guide_swip.pag ├── JacoCategoryJson.json ├── JacoIcon60x60@2x.png ├── JacoIcon76x76@2x~ipad.png ├── JXCategoryView.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── JXPagingView.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── Kingfisher.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── ko_lightning.json ├── ko_red_warn.json ├── ko_sector_countdown.json ├── LicenseBag.bundle │ └── huoshan.licbag ├── light.json ├── live_bottom_barItem_newGift.pag ├── live_combo_send_x100.pag ├── live_combo_send_x15.pag ├── live_combo_send_x30.pag ├── live_combo_send_x50.pag ├── live_face.json ├── live_gift_combo_level1.pag ├── live_gift_combo_level2.pag ├── live_gift_combo_level3.pag ├── live_gift_combo_level4.pag ├── live_gift_combo_level5.pag ├── live_gift_combo_level6.pag ├── live_gift_track_burst.pag ├── live_gift_track_donotstop_ar.pag ├── live_gift_track_donotstop.pag ├── live_gift_track_fire_ar.pag ├── live_gift_track_fire.pag ├── live_gift_track_flash.pag ├── live_gift_track_good_ar.pag ├── live_gift_track_good.pag ├── live_gift_track_greate_ar.pag ├── live_gift_track_greate.pag ├── live_gift_track_legend_ar.pag ├── live_gift_track_legend.pag ├── live_im_zoom_in.json ├── live_im_zoom_out.json ├── live_ko_end.json ├── live_link_voice_wave_blue.json ├── live_link_voice_wave_orange.json ├── live_link_voice_wave_red.json ├── live_link_voice_wave.json ├── live_multi_ink.json ├── live_pk_add_arrow.json ├── live_pk_likeOnly_ar.json ├── live_pk_likeOnly_en.json ├── live_pk_progress_catch_up_ko.pag ├── live_pk_progress_catch_up.pag ├── live_pk_progress_emoji_lose.pag ├── live_pk_progress_emoji_win.pag ├── live_pk_progress_normal.pag ├── live_pk_singleGift_ar.json ├── live_pk_singleGift_en.json ├── live_popup_draw.json ├── live_popup_lose.json ├── live_popup_start.json ├── live_popup_win.json ├── live_rom_box_jump.json ├── live_room_box_enter.json ├── live_room_lucky_box_enter.json ├── live_room_lucky_box_rock.json ├── live_room_swip.json ├── live_sei_carrier.jpg ├── live_share_screen.mp4 ├── live_single_link.json ├── live_single_voice_or_live.json ├── liveroom_casting.pag ├── liveroom_cion_jump.json ├── liveroom_heart_jump.json ├── livevideo_scatter_flowers.json ├── living_bmp.pag ├── loading.json ├── logo_top_image_web1.webp ├── LottiePrivacyInfo.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── lv_goal_progress_35.json ├── lv_goal_progress_50.json ├── lv_goal_progress_65.json ├── lv_goal_progress_80.json ├── lv_goal_progress_99.json ├── MaterialDialogs.bundle │ └── Resources ├── MJRefresh.bundle │ ├── arrow@2x.png │ ├── en.lproj │ ├── ko.lproj │ ├── ru.lproj │ ├── trail_arrow@2x.png │ ├── uk.lproj │ ├── zh-Hans.lproj │ └── zh-Hant.lproj ├── MJRefresh.Privacy.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── ModelResource.bundle │ ├── facefitting │ ├── hairparser │ ├── handmodel │ ├── idream │ ├── mattingmodel │ ├── skeleton_model │ ├── skin_seg │ ├── ttfaceattrmodel │ └── ttfacemodel ├── mopian_6945244021867921415.png ├── Peach Pinky.png ├── PhoneNumberKitPrivacy.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── PhoneNumberMetadata.json ├── pk_end_tips.pag ├── pk_props.mp4 ├── PkgInfo ├── PlugIns │ ├── BroadcastUpload.appex │ ├── BroadcastUploadSetupUI.appex │ └── NotificationService.appex ├── polish_data.json ├── PrivacyInfo.xcprivacy ├── profile_living.json ├── Protobuf_Privacy.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── qingkong_6945244054134538270.png ├── Quality.png ├── RangersAppLog.bundle │ ├── h5bridge-wkwebview.txt │ └── Info.plist ├── RCColor.plist ├── RCConfig.plist ├── README.md ├── RecaptchaEnterpriseSDKResources.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── received_rank_badge.json ├── recharge_discount_bg.json ├── reference_loading.pag ├── refresh_yellow.json ├── RongCloud.bundle │ ├── add@2x.png │ ├── add@3x.png │ ├── arrow@2x.png │ ├── arrow@3x.png │ ├── audio_press_short@2x.png │ ├── audio_press_short@3x.png │ ├── block_notification@2x.png │ ├── block_notification@3x.png │ ├── blue.png │ ├── blue－hover.png │ ├── broken@2x.png │ ├── bubble.png │ ├── burn_video_picture@2x.png │ ├── burn_video_picture@3x.png │ ├── burnPicture@2x.png │ ├── burnPicture@3x.png │ ├── cancelButton@2x.png │ ├── chat_from_bg_normal_dark@2x.png │ ├── chat_from_bg_normal@2x.png │ ├── chat_to_bg_normal_dark@2x.png │ ├── chat_to_bg_normal@2x.png │ ├── chat_to_bg_white_dark@2x.png │ ├── chat_to_bg_white@2x.png │ ├── check.png │ ├── close_burn@2x.png │ ├── close_burn@3x.png │ ├── close.png │ ├── combine_failed@2x.png │ ├── combine_failed@3x.png │ ├── combine_loading@2x.png │ ├── combine_loading@3x.png │ ├── Comment.png │ ├── cs_eva_complete_hover@2x.png │ ├── cs_eva_complete@2x.png │ ├── cs_no@2x.png │ ├── cs_yes_hover@2x.png │ ├── cs_yes@2x.png │ ├── custom_service_evaluation_no_hover.png │ ├── custom_service_evaluation_no.png │ ├── custom_service_evaluation_star_hover.png │ ├── custom_service_evaluation_star.png │ ├── custom_service_evaluation_yes_hover.png │ ├── custom_service_evaluation_yes.png │ ├── custom_service_switch_to_admin_dark@2x.png │ ├── custom_service_switch_to_admin_dark@3x.png │ ├── custom_service_switch_to_admin@2x.png │ ├── custom_service_switch_to_admin@3x.png │ ├── default_collection_portrait@2x.png │ ├── default_collection_portrait@3x.png │ ├── default_discussion_collection_portrait@2x.png │ ├── default_discussion_collection_portrait@3x.png │ ├── default_discussion_portrait@2x.png │ ├── default_discussion_portrait@3x.png │ ├── default_group_portrait@2x.png │ ├── default_group_portrait@3x.png │ ├── default_portrait_msg@2x.png │ ├── default_portrait_msg@3x.png │ ├── default_portrait@2x.png │ ├── default_portrait@3x.png │ ├── delete_message_dark@2x.png │ ├── delete_message_dark@3x.png │ ├── delete_message@2x.png │ ├── delete_message@3x.png │ ├── emoji_btn_delete@2x.png │ ├── emoji_btn_normal.png │ ├── ExcelFile@2x.png │ ├── ExcelFile@3x.png │ ├── exclamation_dark@2x.png │ ├── exclamation@2x.png │ ├── fileicon_video_wall@2x.png │ ├── fileicon_video_wall@3x.png │ ├── files_hover.png │ ├── fire_identify_dark@2x.png │ ├── fire_identify_dark@3x.png │ ├── fire_identify@2x.png │ ├── fire_identify@3x.png │ ├── folder.png │ ├── follow-hover.png │ ├── follow.png │ ├── forward_message_dark@2x.png │ ├── forward_message_dark@3x.png │ ├── forward_message@2x.png │ ├── forward_message@3x.png │ ├── forwardIcon_dark@2x.png │ ├── forwardIcon@2x.png │ ├── from_burn_picture_dark@2x.png │ ├── from_burn_picture_dark@3x.png │ ├── from_burn_picture@2x .png │ ├── from_burn_picture@3x.png │ ├── from_burn_video_picture_dark@2x.png │ ├── from_burn_video_picture_dark@3x.png │ ├── from_burn_video_picture@2x.png │ ├── from_burn_video_picture@3x.png │ ├── from_thumb_image_broken_dark@2x.png │ ├── from_thumb_image_broken_dark@3x.png │ ├── from_thumb_image_broken@2x.png │ ├── from_thumb_image_broken@3x.png │ ├── from_voice_1_dark@2x.png │ ├── from_voice_1_dark@3x.png │ ├── from_voice_1@2x.png │ ├── from_voice_1@3x.png │ ├── from_voice_2_dark@2x.png │ ├── from_voice_2_dark@3x.png │ ├── from_voice_2@2x.png │ ├── from_voice_2@3x.png │ ├── from_voice_3_dark@2x.png │ ├── from_voice_3_dark@3x.png │ ├── from_voice_3@2x.png │ ├── from_voice_3@3x.png │ ├── gif_loadfailed@2x.png │ ├── gif_loadfailed@3x.png │ ├── gif_loading@2x.png │ ├── gif_loading@3x.png │ ├── gif_loadprogress@2x.png │ ├── gif_loadprogress@3x.png │ ├── gif_needload@2x.png │ ├── gif_needload@3x.png │ ├── HQVoiceMsg_failed_tip@2x.png │ ├── HQVoiceMsg_failed_tip@3x.png │ ├── icon_sight_close@2x.png │ ├── inputbar_add_dark@2x.png │ ├── inputbar_add_dark@3x.png │ ├── inputbar_add@2x.png │ ├── inputbar_add@3x.png │ ├── inputbar_emoji_dark@2x.png │ ├── inputbar_emoji_dark@3x.png │ ├── inputbar_emoji@2x.png │ ├── inputbar_emoji@3x.png │ ├── inputbar_keyboard_dark@2x.png │ ├── inputbar_keyboard_dark@3x.png │ ├── inputbar_keyboard@2x.png │ ├── inputbar_keyboard@3x.png │ ├── inputbar_voice_dark@2x.png │ ├── inputbar_voice_dark@3x.png │ ├── inputbar_voice@2x.png │ ├── inputbar_voice@3x.png │ ├── keyboard_burn@2x.png │ ├── keyboard_burn@3x.png │ ├── Keynote@2x.png │ ├── Keynote@3x.png │ ├── map_annotation@2x.png │ ├── map_annotation@3x.png │ ├── message_cell_destruct@2x.png │ ├── message_cell_destruct@3x.png │ ├── message_cell_select_dark@2x.png │ ├── message_cell_select_dark@3x.png │ ├── message_cell_select@2x.png │ ├── message_cell_select@3x.png │ ├── message_cell_unselect_dark@2x.png │ ├── message_cell_unselect_dark@3x.png │ ├── message_cell_unselect@2x.png │ ├── message_cell_unselect@3x.png │ ├── message_fail_dark@2x.png │ ├── message_fail_dark@3x.png │ ├── message_fail@2x.png │ ├── message_fail@3x.png │ ├── message_read_status@2x.png │ ├── message_read_status@3x.png │ ├── Mp3File@2x.png │ ├── Mp3File@3x.png │ ├── navigator_btn_back_dark@2x.png │ ├── navigator_btn_back_dark@3x.png │ ├── navigator_btn_back@2x.png │ ├── navigator_btn_back@3x.png │ ├── navigator_white_back@2x.png │ ├── network_fail_dark@2x.png │ ├── network_fail_dark@3x.png │ ├── network_fail@2x.png │ ├── network_fail@3x.png │ ├── no_message_img_dark@2x.png │ ├── no_message_img@2x.png │ ├── noSolve-hover.png │ ├── noSolve.png │ ├── Numbers@2x.png │ ├── Numbers@3x.png │ ├── OtherFile@2x.png │ ├── OtherFile@3x.png │ ├── Pages@2x.png │ ├── Pages@3x.png │ ├── PdfFile@2x.png │ ├── PdfFile@3x.png │ ├── photo_burn@2x.png │ ├── photo_burn@3x.png │ ├── photo_preview_selected.png │ ├── photo_preview_unselected.png │ ├── photopicker_state_normal.png │ ├── photopicker_state_selected.png │ ├── PictureFile@2x.png │ ├── PictureFile@3x.png │ ├── play_btn_normal@2x.png │ ├── play_btn_normal@3x.png │ ├── play_video@2x.png │ ├── player_shadow_bottom@2x.png │ ├── player_shadow_top@2x.png │ ├── player_slider_pan@2x.png │ ├── player_start_button@2x.png │ ├── player_suspend_button@2x.png │ ├── plugin_item_burn_dark@2x.png │ ├── plugin_item_burn_dark@3x.png │ ├── plugin_item_burn_highlighted_dark@2x.png │ ├── plugin_item_burn_highlighted_dark@3x.png │ ├── plugin_item_burn_highlighted@2x.png │ ├── plugin_item_burn_highlighted@3x.png │ ├── plugin_item_burn@2x.png │ ├── plugin_item_burn@3x.png │ ├── plugin_item_camera_dark@2x.png │ ├── plugin_item_camera_dark@3x.png │ ├── plugin_item_camera_highlighted_dark@2x.png │ ├── plugin_item_camera_highlighted_dark@3x.png │ ├── plugin_item_camera_highlighted@2x.png │ ├── plugin_item_camera_highlighted@3x.png │ ├── plugin_item_camera@2x.png │ ├── plugin_item_camera@3x.png │ ├── plugin_item_card_dark@2x.png │ ├── plugin_item_card_dark@3x.png │ ├── plugin_item_card_highlighted_dark@2x.png │ ├── plugin_item_card_highlighted_dark@3x.png │ ├── plugin_item_card_highlighted@2x.png │ ├── plugin_item_card_highlighted@3x.png │ ├── plugin_item_card@2x.png │ ├── plugin_item_card@3x.png │ ├── plugin_item_file_dark@2x.png │ ├── plugin_item_file_dark@3x.png │ ├── plugin_item_file_highlighted_dark@2x.png │ ├── plugin_item_file_highlighted_dark@3x.png │ ├── plugin_item_file_highlighted@2x.png │ ├── plugin_item_file_highlighted@3x.png │ ├── plugin_item_file@2x.png │ ├── plugin_item_file@3x.png │ ├── plugin_item_location_dark@2x.png │ ├── plugin_item_location_dark@3x.png │ ├── plugin_item_location_highlighted_dark@2x.png │ ├── plugin_item_location_highlighted_dark@3x.png │ ├── plugin_item_location_highlighted@2x.png │ ├── plugin_item_location_highlighted@3x.png │ ├── plugin_item_location@2x.png │ ├── plugin_item_location@3x.png │ ├── plugin_item_picture_dark@2x.png │ ├── plugin_item_picture_dark@3x.png │ ├── plugin_item_picture_highlighted_dark@2x.png │ ├── plugin_item_picture_highlighted_dark@3x.png │ ├── plugin_item_picture_highlighted@2x.png │ ├── plugin_item_picture_highlighted@3x.png │ ├── plugin_item_picture@2x.png │ ├── plugin_item_picture@3x.png │ ├── portrait_kefu@2x.png │ ├── pptFile@2x.png │ ├── pptFile@3x.png │ ├── pub_menu_dark@2x.png │ ├── pub_menu_dark@3x.png │ ├── pub_menu@2x.png │ ├── pub_menu@3x.png │ ├── public_serive_menu_icon@2x.png │ ├── public_serive_menu_icon@3x.png │ ├── public_service_submenu_bg@2x.png │ ├── public_service_submenu_bg@3x.png │ ├── rc_conversation_list_msg_sending@2x.png │ ├── rc_conversation_list_msg_sending@3x.png │ ├── rc_richcontentmsg_placeholder@2x.png │ ├── rc_setting@2x.png │ ├── rc_setting@3x.png │ ├── receipt_hover.png │ ├── receipt.png │ ├── referencing_view_dismiss_icon@2x.png │ ├── referencing_view_dismiss_icon@3x.png │ ├── Resolved-hover.png │ ├── Resolved.png │ ├── return@2x.png │ ├── return@3x.png │ ├── right_arrow@2x.png │ ├── right_arrow@3x.png │ ├── selected_full.png │ ├── sendMsg_failed_tip_dark@2x.png │ ├── sendMsg_failed_tip_dark@3x.png │ ├── sendMsg_failed_tip@2x.png │ ├── sendMsg_failed_tip@3x.png │ ├── sight_camera_switch@2x.png │ ├── sight_download_failed@2x.png │ ├── sight_download_failed@3x.png │ ├── sight_file_icon@2x.png │ ├── sight_file_icon@3x.png │ ├── sight_label_shadow@2x.png │ ├── sight_list_button@2x.png │ ├── sight_message_icon@2x.png │ ├── sight_message_icon@3x.png │ ├── sight_pause_btn@2x.png │ ├── sight_pause_btn@3x.png │ ├── sight_play_btn@2x.png │ ├── sight_play_btn@3x.png │ ├── sight_preview_cancel@2x.png │ ├── sight_preview_cancel@3x.png │ ├── sight_preview_done@2x.png │ ├── sight_preview_done@3x.png │ ├── sight_top_toolbar_close@2x.png │ ├── sight_top_toolbar_close@3x.png │ ├── sms-received.caf │ ├── template.json │ ├── text_burn_img@2x.png │ ├── text_burn_img@3x.png │ ├── TextFile@2x.png │ ├── TextFile@3x.png │ ├── to_thumb_image_broken_dark@2x.png │ ├── to_thumb_image_broken_dark@3x.png │ ├── to_thumb_image_broken@2x.png │ ├── to_thumb_image_broken@3x.png │ ├── to_voice_1_dark@2x.png │ ├── to_voice_1_dark@3x.png │ ├── to_voice_1@2x.png │ ├── to_voice_1@3x.png │ ├── to_voice_2_dark@2x.png │ ├── to_voice_2_dark@3x.png │ ├── to_voice_2@2x.png │ ├── to_voice_2@3x.png │ ├── to_voice_3_dark@2x.png │ ├── to_voice_3_dark@3x.png │ ├── to_voice_3@2x.png │ ├── to_voice_3@3x.png │ ├── translation_from_bg_normal_dark@2x.png │ ├── translation_from_bg_normal@2x.png │ ├── unselected_full.png │ ├── up_dark@2x.png │ ├── up_dark@3x.png │ ├── up@2x.png │ ├── up@3x.png │ ├── video_icon_play@2x.png │ ├── VideoFile@2x.png │ ├── VideoFile@3x.png │ ├── voice_1.png │ ├── voice_2.png │ ├── voice_3.png │ ├── voice_4.png │ ├── voice_5.png │ ├── voice_6.png │ ├── voice_7.png │ ├── voice_8.png │ ├── voice_burn@2x.png │ ├── voice_burn@3x.png │ ├── voice_unread@2x.png │ ├── voice_unread@3x.png │ ├── voice_volume0@2x.png │ ├── voip │ ├── WordFile@2x.png │ └── WordFile@3x.png ├── sayhi.json ├── SC_Info │ ├── JACO.sinf │ ├── JACO.supf │ ├── JACO.supp │ ├── JACO.supx │ └── Manifest.plist ├── selective.json ├── share_screen_audio_loading.json ├── shareView_casting.pag ├── shime.json ├── shortVideoPauseRecord.json ├── shortVideoRecording.json ├── shortVideoStartRecord.json ├── Silence.wav ├── small_playback_lottie.json ├── small_record_lottie.json ├── splash_loading_pag_bmp.pag ├── splash_toHome_pag.pag ├── StickerResource.bundle │ └── stickers ├── supporter_rank_badge.json ├── SwiftProtobuf.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── textPacketColor.json ├── textTF.bundle │ ├── Almas.png │ ├── Almas.ttf │ ├── ArefRuqaa.png │ ├── ArefRuqaa.ttf │ ├── CallOfOpsDuty.otf │ ├── CallOfOpsDuty.png │ ├── Classic.png │ ├── Classic.ttf │ ├── Dortmund.otf │ ├── Dortmund.png │ ├── Kayana.otf │ ├── Kayana.png │ ├── Kufam.png │ ├── Kufam.ttf │ ├── LamaSans-ExtraBold.otf │ ├── LamaSans.otf │ ├── LamaSans.png │ ├── Mailand.otf │ ├── Mailand.png │ ├── NotoNastaliqUrdu.png │ ├── NotoNastaliqUrdu.ttf │ ├── RedditSans.png │ ├── RedditSans.ttf │ ├── Sarmady.otf │ ├── Sarmady.png │ ├── Scheherazade.png │ ├── Scheherazade.ttf │ ├── SFArabic.ttf │ ├── SpicyWasabi.png │ ├── SpicyWasabi.ttf │ ├── SuperSedan.png │ ├── SuperSedan.ttf │ ├── textTF.json │ ├── Thestral.otf │ ├── Thestral.png │ ├── Vazirmatn.png │ └── Vazirmatn.ttf ├── thin ├── three_dot.json ├── Toast-Swift.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── tongnian_6945244030104649736.png ├── tree.txt ├── TuringShield.bundle │ └── PrivacyInfo.xcprivacy ├── version.info ├── video_double_like.json ├── video_edit_watermark.png ├── video_favorite.json ├── video_follow.json ├── video_live_now.json ├── video_music_play.json ├── video_survey_great.pag ├── video_survey_not_bad.pag ├── video_survey_poor.pag ├── Warm Man.png ├── Warm.png ├── Warmfood_7165158837891104769.png ├── Water Mist.png └── ZLPhotoBrowser.bundle ├── ar.lproj ├── de.lproj ├── en.lproj ├── es-419.lproj ├── fr.lproj ├── id.lproj ├── it.lproj ├── ja-US.lproj ├── ko.lproj ├── ms.lproj ├── pt-BR.lproj ├── ru.lproj ├── tr.lproj ├── vi.lproj ├── zh-Hans.lproj ├── zh-Hant.lproj ├── zl_addPhoto@2x.png ├── zl_addPhoto@3x.png ├── zl_adjust_selected@2x.png ├── zl_adjust_selected@3x.png ├── zl_adjust@2x.png ├── zl_adjust@3x.png ├── zl_albumSelect@2x.png ├── zl_albumSelect@3x.png ├── zl_arrow_down_dark@3x.png ├── zl_arrow_down_light@3x.png ├── zl_arrow_down@2x.png ├── zl_arrow_down@3x.png ├── zl_ashbin_open@2x.png ├── zl_ashbin_open@3x.png ├── zl_ashbin@2x.png ├── zl_ashbin@3x.png ├── zl_brightness_selected@2x.png ├── zl_brightness_selected@3x.png ├── zl_brightness@2x.png ├── zl_brightness@3x.png ├── zl_btn_circle@2x.png ├── zl_btn_circle@3x.png ├── zl_btn_original_circle@2x.png ├── zl_btn_original_circle@3x.png ├── zl_btn_original_selected@2x.png ├── zl_btn_original_selected@3x.png ├── zl_btn_selected_icon@2x.png ├── zl_btn_selected_icon@3x.png ├── zl_btn_selected@2x.png ├── zl_btn_selected@3x.png ├── zl_btn_unselected@2x.png ├── zl_btn_unselected@3x.png ├── zl_camera_close@2x.png ├── zl_camera_close@3x.png ├── zl_clip@2x.png ├── zl_clip@3x.png ├── zl_close@2x.png ├── zl_close@3x.png ├── zl_contrast_selected@2x.png ├── zl_contrast_selected@3x.png ├── zl_contrast@2x.png ├── zl_contrast@3x.png ├── zl_defaultphoto.png ├── zl_download_close@3x.png ├── zl_drawLine_selected@2x.png ├── zl_drawLine_selected@3x.png ├── zl_drawLine@2x.png ├── zl_drawLine@3x.png ├── zl_editImage_tag@2x.png ├── zl_editImage_tag@3x.png ├── zl_filter_selected@2x.png ├── zl_filter_selected@3x.png ├── zl_filter@2x.png ├── zl_filter@3x.png ├── zl_flash_off@2x.png ├── zl_flash_off@3x.png ├── zl_flash_on@2x.png ├── zl_flash_on@3x.png ├── zl_focus@2x.png ├── zl_focus@3x.png ├── zl_ic_left@2x.png ├── zl_ic_left@3x.png ├── zl_ic_right@2x.png ├── zl_ic_right@3x.png ├── zl_icon_icloud@2x.png ├── zl_icon_icloud@3x.png ├── zl_imageSticker@2x.png ├── zl_imageSticker@3x.png ├── zl_livePhoto@2x.png ├── zl_livePhoto@3x.png ├── zl_loading_dark@2x.png ├── zl_loading_dark@3x.png ├── zl_loading_light@2x.png ├── zl_loading_light@3x.png ├── zl_mix_delete@2x.png ├── zl_mix_delete@3x.png ├── zl_mosaic_selected@2x.png ├── zl_mosaic_selected@3x.png ├── zl_mosaic@2x.png ├── zl_mosaic@3x.png ├── zl_mute_off.png ├── zl_mute_on.png ├── zl_navBack@2x.png ├── zl_navBack@3x.png ├── zl_navClose_dark@3x.png ├── zl_navClose@3x.png ├── zl_pauseButtonWhite@2x.png ├── zl_pauseButtonWhite@3x.png ├── zl_play_icon.png ├── zl_playButtonWhite@2x.png ├── zl_playButtonWhite@3x.png ├── zl_playVideo@2x.png ├── zl_playVideo@3x.png ├── zl_preview_nav_bg@3x.png ├── zl_redo_disable@2x.png ├── zl_redo_disable@3x.png ├── zl_redo@2x.png ├── zl_redo@3x.png ├── zl_retake@2x.png ├── zl_retake@3x.png ├── zl_revoke_disable@2x.png ├── zl_revoke_disable@3x.png ├── zl_revoke@2x.png ├── zl_revoke@3x.png ├── zl_right_arrow@2x.png ├── zl_right_arrow@3x.png ├── zl_right@2x.png ├── zl_right@3x.png ├── zl_rotateimage@2x.png ├── zl_rotateimage@3x.png ├── zl_saturation_selected@2x.png ├── zl_saturation_selected@3x.png ├── zl_saturation@2x.png ├── zl_saturation@3x.png ├── zl_shadow@3x.png ├── zl_takePhoto@2x.png ├── zl_takePhoto@3x.png ├── zl_textSticker@2x.png ├── zl_textSticker@3x.png ├── zl_toggle_camera@2x.png ├── zl_toggle_camera@3x.png ├── zl_video@2x.png ├── zl_video@3x.png ├── zl_videoLoadFailed@2x.png ├── zl_videoLoadFailed@3x.png ├── zl_warning@2x.png └── zl_warning@3x.png 287 directories, 862 files
前言为何调试 Flutter Engine ？学习查 crash准备工作1. Flutter 版本Flutter 3.7.12 • Engine 1a65d409c7不一定是这个版本，但是你要记住你自己选择的版本，并找到对应的 dsym。2. 下载官方 iOS dSYM # 下载 (115 MB) curl -L -o Flutter.dSYM.zip \ "https://storage.googleapis.com/flutter_infra_release/flutter/1a65d409c7a1438a34d21b60bf30a6fd5db59314/ios-release/Flutter.dSYM.zip" # 解压 unzip -o -q Flutter.dSYM.zip3. UUID 验证dSYM UUID:x86_64 (Simulator): 4C4C4472-5555-3144-A169-E9E012AAE73B arm64 (Device): 4C4C4415-5555-3144-A112-3C0FFF4C00D2Engine Binary UUID:模拟器 (ios-arm64_x86_64-simulator):x86_64: 4C4C4472-5555-3144-A169-E9E012AAE73B ✅真机 (ios-arm64):arm64: 4C4C4415-5555-3144-A112-3C0FFF4C00D2 ✅完美匹配！模拟器和真机都能用！这一步搞定后，后面的就很 easy 了。步骤 1: 创建测试项目cd ~/projs/analyse_flutter_source flutter create ios_debug_demo --platforms=ios cd ios_debug_demo步骤 2: 配置 LLDB Source Mapping编辑 ~/.lldbinit（一次性配置）:# Flutter Engine 源码映射 settings set target.source-map /Users/runner/work/engine/src /Users/mac/flutter-engine/src步骤 3: 在 Xcode 中打开项目cd ~/projs/analyse_flutter_source/ios_debug_demo flutter build ios --release --simulator open ios/Runner.xcworkspace步骤 4: 配置 Xcode选择模拟器目标：Product → Destination → iPhone 15 Pro (或任意模拟器)配置 Scheme：Product → Scheme → Edit Scheme...Run → Info → Build Configuration: ReleaseRun → Options → ✅ Debug executable步骤 5: 添加 dSYM方法 1: 拖拽到 Xcode直接把 ~/projs/analyse_flutter_source/Flutter.dSYM 拖到 Xcode 的 Project Navigator方法 2: 命令行复制# 复制到项目构建目录 cp -R ~/projs/analyse_flutter_source/Flutter.dSYM \ ~/Library/Developer/Xcode/DerivedData/Runner-*/Build/Products/Release-iphonesimulator/步骤 6: 设置断点符号断点（iOS 工程师的最爱）:Debug → Breakpoints → Create Symbolic BreakpointSymbol: -[FlutterViewController viewDidLoad]Module: Flutter (可选，但推荐)最后看一下效果：
出来鞭尸了！ijkplayer iOS 编译完全指南（Xcode 26.0.1 下，修复部分问题）
前言“GitHub 上的 ijkplayer 是‘尸体’，B站内部的 ijkplayer 是‘活体’。”那么，鞭尸有何帮助？老项目应该还有一些在维护，需要做一些适配的时候，我能提供一些帮助新人想上手直播拉流的，可以参考一下本文档。概述macOS 上为 iOS 平台如何编译 ijkplayer ？此文为您解答ijkplayer 是基于 FFmpeg 的轻量级 Android/iOS 视频播放器，具有以下特点：支持 iOS/Android 平台基于 FFmpeg n4.0 版本支持硬件加速解码支持直播流播放 (RTMP, HLS)可定制化的编解码器支持编译结果总览成功编译的架构 | 架构 | 目标平台 | SDK | 库文件大小 | 编译时间 | |-----|---------|-----|-----------|---------| | **arm64** | iOS 真机 | iPhoneOS | ~25 MB | ~8分钟 | | **x86_64** | iOS 模拟器 | iPhoneSimulator | ~31 MB | ~8分钟 | | **Universal** | 通用库 | 合并 | ~56 MB | ~1分钟 | 生成的库文件build/universal/lib/ ├── libavcodec.a (37.6 MB) - 编解码器核心库 ├── libavfilter.a (1.4 MB) - 音视频过滤器库 ├── libavformat.a (10.9 MB) - 封装格式处理库 ├── libavutil.a (3.0 MB) - 工具函数库 ├── libswresample.a (696 KB) - 音频重采样库 └── libswscale.a (4.3 MB) - 视频缩放库环境要求与配置系统要求macOS版本: 10.15+ (Catalina 或更高)Xcode版本: 14.0+ (本次使用 26.0.1)磁盘空间: 至少 5GB 可用空间内存: 建议 8GB+必需工具# 安装 Homebrew (如果未安装) /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # 安装必需工具 brew install yasm # 汇编器 brew install pkg-config # 包配置工具 (可选) brew install nasm # 另一个汇编器 (可选) # 验证 Xcode 命令行工具 xcode-select --install xcode-select -p环境变量配置# 添加到 ~/.zshrc 或 ~/.bash_profile export PATH="/usr/local/bin:$PATH" export DEVELOPER_DIR=$(xcode-select -p)项目初始化与配置修改1. 克隆项目git clone https://github.com/bilibili/ijkplayer.git ijkplayer-ios cd ijkplayer-ios git checkout -B latest k0.8.82. 初始化 iOS 构建环境./init-ios.sh这个脚本会：下载 gas-preprocessor (ARM 汇编预处理器)拉取 FFmpeg 源代码为每个架构创建 FFmpeg 分支设置配置文件链接3. 关键配置修改3.1 架构配置 (compile-ffmpeg.sh)# 只使用现代架构 FF_ALL_ARCHS_MODERN="arm64 x86_64" FF_ALL_ARCHS=$FF_ALL_ARCHS_MODERN3.2 Xcode 26+ 兼容性修复 (tools/do-compile-ffmpeg.sh)移除废弃的 Bitcode 标志:# arm64 架构 elif [ "$FF_ARCH" = "arm64" ]; then FF_XCODE_BITCODE="" # 原来是 "-fembed-bitcode" # x86_64 架构 elif [ "$FF_ARCH" = "x86_64" ]; then FF_XCODE_BITCODE="" # 原来是 "-fembed-bitcode"更新最低 iOS 版本:# arm64 FF_XCRUN_OSVERSION="-miphoneos-version-min=12.0" # x86_64 FF_XCRUN_OSVERSION="-mios-simulator-version-min=12.0"添加编译器兼容性标志:FFMPEG_CFLAGS="$FFMPEG_CFLAGS -Wno-error=incompatible-function-pointer-types" FFMPEG_CFLAGS="$FFMPEG_CFLAGS -Wno-error=int-conversion"4. 选择编解码器配置cd ios ln -s module-lite.sh config/module.sh # 精简版 (推荐) # 或 ln -s module-default.sh config/module.sh # 完整版编译步骤详解完整编译流程cd ios # 1. 清理之前的编译文件 ./compile-ffmpeg.sh clean # 2. 编译所有架构 (约15-20分钟) ./compile-ffmpeg.sh all # 或分步编译： ./compile-ffmpeg.sh arm64 # 编译真机版本 ./compile-ffmpeg.sh x86_64 # 编译模拟器版本 ./compile-ffmpeg.sh lipo # 合并为通用库编译过程说明阶段 1: 配置 (Configure)检测编译环境生成 Makefile配置编解码器选项设置编译标志阶段 2: 编译 (Compile)编译 libavutil (基础工具)编译 libavcodec (编解码器)编译 libavformat (格式处理)编译 libavfilter (过滤器)编译 libswscale (缩放)编译 libswresample (重采样)阶段 3: 安装 (Install)复制库文件到输出目录安装头文件生成 pkg-config 文件阶段 4: 合并 (Lipo)使用 lipo 工具合并多架构生成通用库文件合并头文件编译输出结构ios/build/ ├── ffmpeg-arm64/ # ARM64 架构构建 │ └── output/ │ ├── include/ # 头文件 │ │ ├── libavcodec/ │ │ ├── libavformat/ │ │ ├── libavutil/ │ │ └── ... │ └── lib/ # 静态库 │ ├── libavcodec.a │ ├── libavformat.a │ └── ... ├── ffmpeg-x86_64/ # x86_64 架构构建 │ └── output/ │ ├── include/ │ └── lib/ └── universal/ # 通用库 (Fat Binary) ├── include/ # 合并的头文件 └── lib/ # 合并的库文件 ├── libavcodec.a # 包含 arm64 + x86_64 ├── libavformat.a └── ...验证编译结果检查库架构# 验证通用库包含的架构 lipo -info build/universal/lib/libavcodec.a # 输出: Architectures in the fat file: libavcodec.a are: x86_64 arm64 # 查看库详细信息 lipo -detailed_info build/universal/lib/libavcodec.a # 检查符号表 nm build/universal/lib/libavcodec.a | grep avcodec_version验证头文件# 确认头文件存在 ls -la build/universal/include/libavcodec/avcodec.h ls -la build/universal/include/libavformat/avformat.h集成到 iOS 项目方法一：使用 Demo 项目# 打开 Demo 项目 open IJKMediaDemo/IJKMediaDemo.xcodeproj # 在 Xcode 中： # 1. 选择目标设备 (模拟器或真机) # 2. 点击 Run 按钮 # 3. 测试视频播放功能方法二：集成到自己的项目1. 添加库文件将以下文件添加到项目：build/universal/lib/*.a # 所有静态库2. 配置 Build SettingsHeader Search Paths: $(PROJECT_DIR)/path/to/build/universal/include Library Search Paths: $(PROJECT_DIR)/path/to/build/universal/lib Other Linker Flags: -lz -lbz2 -liconv3. 添加系统框架在 Build Phases → Link Binary With Libraries 添加：VideoToolbox.frameworkCoreMedia.frameworkCoreVideo.frameworkCoreGraphics.frameworkAVFoundation.frameworkAudioToolbox.frameworkUIKit.frameworkFoundation.frameworkQuartzCore.frameworkOpenGLES.frameworkCFNetwork.frameworkSecurity.frameworkMobileCoreServices.framework4. 示例代码#import <IJKMediaFramework/IJKMediaFramework.h> // 创建播放器 IJKFFMoviePlayerController *player = [[IJKFFMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:@"http://example.com/video.mp4"] withOptions:nil]; // 准备播放 [player prepareToPlay]; // 添加播放视图 player.view.frame = self.view.bounds; [self.view addSubview:player.view]; // 开始播放 [player play];支持的功能配置编解码器支持 (module-lite.sh)解码器 (Decoders)视频: H.264, HEVC/H.265, VP8, VP9, FLV, H.263音频: AAC, AAC-LATM, MP3, FLAC编码器 (Encoders)图像: PNG (用于截图)封装格式 (Formats)输入: FLV, MP4/MOV, HLS, MPEG-TS, MKV/WebM输出: MP4网络协议 (Protocols)HTTP/HTTPSRTMP/RTMPTHLSFTPTCP/UDP文件系统编译优化选项--enable-small: 减小库文件大小--enable-optimizations: 启用优化--enable-neon: ARM NEON 优化 (仅 ARM64)--enable-debug: 包含调试符号--enable-pic: 位置无关代码常见问题与解决方案问题 1: yasm 未找到错误: yasm not found 解决: brew install yasm问题 2: 编译器类型检查错误错误: incompatible function pointer types 解决: 已通过添加 -Wno-error=incompatible-function-pointer-types 解决问题 3: iOS 版本 API 不兼容错误: 'SecIdentityCreate' is only available on iOS 11.2 or newer 解决: 更新最低 iOS 版本到 12.0问题 4: Bitcode 相关错误错误: -mllvm and -bitcode_bundle cannot be used together 解决: 移除所有 -fembed-bitcode 标志问题 5: 架构不匹配错误: Undefined symbols for architecture x86_64 解决: 确保编译了所需架构并正确链接性能指标库文件大小对比配置总大小说明module-lite.sh~56 MB精简版，基本编解码器module-default.sh~120 MB完整版，所有编解码器module-lite-hevc.sh~65 MB精简版 + HEVC编译时间操作时间CPU 使用率清理1-2 分钟低编译 arm647-10 分钟高 (100%)编译 x86_647-10 分钟高 (100%)合并库<1 分钟低总计15-22 分钟-编译日志与警告说明预期警告 (可忽略)废弃 API 警告warning: 'codec' is deprecated warning: 'refcounted_frames' is deprecated这些是 FFmpeg 内部的兼容性代码。函数指针类型警告warning: incompatible function pointer types已通过编译标志抑制为警告。NEON 指令警告warning: instruction movi.2d with immediate #0ARM 汇编优化相关，不影响功能。更新与维护更新 FFmpeg 版本cd ijkplayer-ios git pull origin master ./init-ios.sh # 重新应用配置修改 # 重新编译清理编译缓存./compile-ffmpeg.sh clean rm -rf build/ rm -rf ffmpeg-*/切换编解码器配置cd config rm module.sh ln -s module-default.sh module.sh # 或其他配置 cd .. ./compile-ffmpeg.sh clean ./compile-ffmpeg.sh all参考资源官方文档ijkplayer GitHubFFmpeg 官网Apple Developer - Xcode相关项目VLC for iOSMobileFFmpegFFmpeg-iOS-build技术规范H.264 规范HEVC/H.265 规范HLS 规范许可证信息ijkplayer许可证: LGPL v2.1+版权所有: BilibiliFFmpeg许可证: LGPL v2.1+ (本配置)可选 GPL 许可 (需要重新配置)使用注意LGPL 要求动态链接或提供目标文件如果修改了 FFmpeg 源码，需要公开修改部分商业使用请仔细阅读许可证条款总结成功适配 Xcode 26.0.1移除废弃的 Bitcode 支持更新最低 iOS 版本到 12.0生成 arm64 和 x86_64 架构库创建通用库 (Universal Binary)验证所有库文件正确生成编译产物可直接用于 iOS 应用开发，支持真机和模拟器调试。
前言阿里内部使用的 windvane 容器原理剖析抛出问题端上设计缺陷问题处理（iOS首页白屏，Bridge 调用卡顿）统一两端方案安全加固性能优化（加载速度过慢）双端感知（H5 内部跳转（非原生跳转） 情况下 端上如何感知）H5 沉浸式页面（如全屏视频、游戏、直播）解决！时间线--------------------------------------------------------- | WindVane架构演进 | --------------------------------------------------------- | 年份/阶段 | 2013-2014 | 2015 | now | --------------------------------------------------------- | 交互时 | Hybrid API| | | | | 平台化 | | | --------------------------------------------------------- | 下载时 | | 预加载 | | | | | HTTP-DNS | | | | | SPDY | | --------------------------------------------------------- | 渲染时 | | | 渲染 | ---------------------------------------------------------前期主要处理交互问题，后期开始处理下载问题以及渲染问题。首页白屏问题分两步app 第一次进入 wk 会白屏，解决方案：适当时机（比如进入骑手个人中心页面后）就启动一个空白 wkwebview。统一两端方案这个不用说，web 负责渲染 UI，逻辑部分通过 Javascript 各自端上实现。我们分开来看web 页面渲染只需要 Html + CSS（当然，部分 UI 展示需要借助一定的 JS 逻辑）Javascript 通过 Web 容器提供的通道来实现双向通信安全加固三个方案：参数校验（Schema Validation）参数不对则拒绝来源校验（Origin Check）不是 饿了么 host， 则拒绝防重放攻击每次 invoke 带唯一 nonce + 时间戳；服务端校验防止重复提交。性能优化（加载速度过慢）离线包。静态资源（js、html、css）本地加载即可。亮点WindVane 采用 “预注入 + 动态增强” 双阶段注入策略，在页面加载前完成基础能力注入，运行时按需注入业务 SDK。流程图：阶段一：预注入 核心 js时机：WKWebView 初始化后、loadRequest 之前注入的内容：window.WindVanePromise 风格的 invoke(method, params) 方法__callbacks 映射表基础事件监听（如 onPageReady）注意为什么必须在 loadRequest 前注入？确保 H5 页面第一行 JS 就能调用 Bridge，避免“Bridge not ready”错误。阶段 2：动态注入业务 SDK（按需）时机：收到 H5 的特定信号（如 ）方式：从本地缓存或 CDN 下载 login_sdk.js通过 evaluateJavaScript 注入优势：减少首屏 JS 体积按业务域隔离能力（防滥用）数据：淘宝早期因 Bridge 未就绪导致的 JS 错误率 >15%，注入前置后降至 <0.1%。保证跨平台一致性：前端无需写 if (isIOS) ... else if (isAndroid) ...。双端感知监听 History API：WindVane 会注入 JS 代码，劫持 pushState / replaceState：const originalPush = history.pushState; history.pushState = function() { originalPush.apply(history, arguments); // 通知原生：页面已跳转 windvane.notifyPageChange(location.href); };H5 沉浸式页面什么是“沉浸式”？页面需要 隐藏状态栏、导航栏可能要求 横屏锁定用户手势（如下滑）可能触发 退出全屏 而非返回上一页原生 UI（如 ActionBar）需动态隐藏/显示WindVane 如何处理？扩展 JSBridge API提供类似：// H5 主动请求沉浸式 windvane.setImmersiveMode({ immersive: true, orientation: 'landscape', hideNavBar: true });原生容器收到后，动态调整 Activity 的 UI 和屏幕方向。手势代理机制WindVane 监听 WebView 的 touch 事件若 H5 声明“当前处于沉浸式”，则拦截系统返回手势，交由 H5 处理（如退出全屏）通过 shouldOverrideKeyEvent 或自定义 GestureDetector 实现生命周期透传当 App 进入后台（onPause），WindVane 主动调用 H5 注册的 onAppBackground() 回调H5 可在此暂停视频、释放资源权限预声明在离线包配置中声明“该页面需要沉浸式权限”WindVane 加载前检查，避免运行时失败虚拟页面栈管理WindVane 维护一个 H5 内部页面栈（独立于原生 Activity 栈）每次 notifyPageChange 就 push 一个新“虚拟页面”按返回键时，先 pop 虚拟栈；栈空才关闭 WebView动态埋点上报收到 notifyPageChange 后，自动触发新页面的 PV 上报性能指标（FCP、LCP）按虚拟页面重置总结+---------------------+--------------------------------------+ | 问题 | WindVane 方案 | +---------------------+--------------------------------------+ | 首屏白屏 | 预注入 + 离线包 → H5秒开 | | Bridge 调用卡顿 | 异步队列 + 批量合并消息 | | 内存泄漏 | 自动清理 callback + WebView 复用池 | | JS 执行阻塞 UI | 所有 evaluateJavaScript 放子线程调度 | +---------------------+--------------------------------------+具体的阿里内部有在大会分享过：活动家（https://www.huodongjia.com/）
前言最近在开发一款 Flutter 学习 APP，主要通过用户提问的方式学习 Flutter，为了确保用户的隐私以及回复的效率，我打算自己实现一个本地模型，供 AI 助手调用，UI 已经写的七七八八了：开始
前言目前跨平台方面，除了Flutter 就是 React Native（RN） ，我们今天来玩转一下 RN。前期准备先准备 node 环境：brew install node可以看到如下输出：==> Auto-updating Homebrew... Adjust how often this is run with `$HOMEBREW_AUTO_UPDATE_SECS` or disable with `$HOMEBREW_NO_AUTO_UPDATE=1`. Hide these hints with `$HOMEBREW_NO_ENV_HINTS=1` (see `man brew`). ==> Auto-updated Homebrew! Updated 2 taps (homebrew/core and homebrew/cask). ==> New Formulae aklomp-base64: Fast Base64 stream encoder/decoder in C99, with SIMD acceleration asm-lsp: Language server for NASM/GAS/GO Assembly bulletty: Pretty feed reader (ATOM/RSS) that stores articles in Markdown files claude-code-router: Tool to route Claude Code requests to different models and customize any request claude-code-templates: CLI tool for configuring and monitoring Claude Code container: Create and run Linux containers using lightweight virtual machines container-canary: Test and validate container requirements against versioned manifests corepack: Package acting as bridge between Node projects and their package managers cpptrace: Simple, portable, and self-contained stacktrace library for C++11 and newer docmd: Minimal Markdown documentation generator doh: Stand-alone DNS-over-HTTPS resolver using libcurl eigen@3: C++ template library for linear algebra fake-gcs-server: Emulator for Google Cloud Storage API filebrowser: Web File Browser framework-tool-tui: TUI for controlling and monitoring Framework Computers hardware gcl: GNU Common Lisp getparty: Multi-part HTTP download manager gitlab-ci-linter: Command-line tool to lint GitLab CI YAML files gocheat: TUI Cheatsheet for keybindings, hotkeys and more goclone: Website Cloner hack-browser-data: Command-line tool for decrypting and exporting browser data haraka: Fast, highly extensible, and event driven SMTP server hexhog: Hex viewer/editor intelli-shell: Like IntelliSense, but for shells kibi: Text editor in ≤1024 lines of code, written in Rust ktea: Kafka TUI client magika: Fast and accurate AI powered file content types detection mark: Sync your markdown files with Confluence pages mcat: Terminal image, video, directory, and Markdown viewer mysql-to-sqlite3: Transfer data from MySQL to SQLite node@24: Open-source, cross-platform JavaScript runtime environment openlist: New AList fork addressing anti-trust issues openssl@1.1: Cryptography and SSL/TLS Toolkit permify: Open-source authorization service & policy engine based on Google Zanzibar postgres-language-server: Language Server for Postgres qcoro6: C++ Coroutines for Qt quint: Core tool for the Quint specification language rails-mcp-server: MCP server for Rails applications reddix: Reddit, refined for the terminal rumdl: Markdown Linter and Formatter written in Rust sqlite3-to-mysql: Transfer data from SQLite to MySQL supabase: Open source Firebase alternative taskline: Tasks, boards & notes for the command-line habitat teamtype: Peer-to-peer, editor-agnostic collaborative editing of local text files ts_query_ls: LSP implementation for Tree-sitter's query files tscriptify: Golang struct to TypeScript class/interface converter tuios: Terminal UI OS (Terminal Multiplexer) You have 3 outdated formulae installed. ==> Fetching downloads for: node ==> Downloading https://ghcr.io/v2/homebrew/core/node/manifests/25.1.0_1 ########################################################################## 100.0% ==> Fetching dependencies for node: brotli, c-ares, icu4c@77, libnghttp2, libnghttp3, libngtcp2, libuv, simdjson, sqlite, uvwasi, lz4, xz and zstd ==> Downloading https://ghcr.io/v2/homebrew/core/brotli/manifests/1.2.0 ########################################################################## 100.0% ==> Fetching brotli ==> Downloading https://ghcr.io/v2/homebrew/core/brotli/blobs/sha256:c9d272f3ac33 ########################################################################## 100.0% ==> Downloading https://ghcr.io/v2/homebrew/core/c-ares/manifests/1.34.5-1 ########################################################################## 100.0% ==> Fetching c-ares ==> Downloading https://ghcr.io/v2/homebrew/core/c-ares/blobs/sha256:c152939c8cbf ########################################################################## 100.0% ==> Downloading https://ghcr.io/v2/homebrew/core/icu4c/77/manifests/77.1 ########################################################################## 100.0% ==> Fetching icu4c@77 ==> Downloading https://ghcr.io/v2/homebrew/core/icu4c/77/blobs/sha256:54d609febe ########################################################################## 100.0% ==> Downloading https://ghcr.io/v2/homebrew/core/libnghttp2/manifests/1.68.0 ########################################################################## 100.0% ==> Fetching libnghttp2 ==> Downloading https://ghcr.io/v2/homebrew/core/libnghttp2/blobs/sha256:b848ec2c ########################################################################## 100.0% ==> Downloading https://ghcr.io/v2/homebrew/core/libnghttp3/manifests/1.12.0 ########################################################################## 100.0% ==> Fetching libnghttp3 ==> Downloading https://ghcr.io/v2/homebrew/core/libnghttp3/blobs/sha256:81311931 ########################################################################## 100.0% ==> Downloading https://ghcr.io/v2/homebrew/core/libngtcp2/manifests/1.17.0 ########################################################################## 100.0% ==> Fetching libngtcp2 ==> Downloading https://ghcr.io/v2/homebrew/core/libngtcp2/blobs/sha256:279e17de0 ########################################################################## 100.0% ==> Downloading https://ghcr.io/v2/homebrew/core/libuv/manifests/1.51.0-1 ########################################################################## 100.0% ==> Fetching libuv ==> Downloading https://ghcr.io/v2/homebrew/core/libuv/blobs/sha256:89296bb1520f6 ########################################################################## 100.0% ==> Downloading https://ghcr.io/v2/homebrew/core/simdjson/manifests/4.2.1 ########################################################################## 100.0% ==> Fetching simdjson ==> Downloading https://ghcr.io/v2/homebrew/core/simdjson/blobs/sha256:c1499dc97a ########################################################################## 100.0% ==> Downloading https://ghcr.io/v2/homebrew/core/sqlite/manifests/3.51.0 ########################################################################## 100.0% ==> Fetching sqlite ==> Downloading https://ghcr.io/v2/homebrew/core/sqlite/blobs/sha256:643e8196600c ########################################################################## 100.0% ==> Downloading https://ghcr.io/v2/homebrew/core/uvwasi/manifests/0.0.23-1 ########################################################################## 100.0% ==> Fetching uvwasi ==> Downloading https://ghcr.io/v2/homebrew/core/uvwasi/blobs/sha256:74534d557b06 ########################################################################## 100.0% ==> Downloading https://ghcr.io/v2/homebrew/core/lz4/manifests/1.10.0-1 ########################################################################## 100.0% ==> Fetching lz4 ==> Downloading https://ghcr.io/v2/homebrew/core/lz4/blobs/sha256:c30d8dad4decfc0 ########################################################################## 100.0% ==> Downloading https://ghcr.io/v2/homebrew/core/xz/manifests/5.8.1 ########################################################################## 100.0% ==> Fetching xz ==> Downloading https://ghcr.io/v2/homebrew/core/xz/blobs/sha256:ce65e4c93e377bef ########################################################################## 100.0% ==> Downloading https://ghcr.io/v2/homebrew/core/zstd/manifests/1.5.7-1 ########################################################################## 100.0% ==> Fetching zstd ==> Downloading https://ghcr.io/v2/homebrew/core/zstd/blobs/sha256:873feb2d747bb2 ########################################################################## 100.0% ==> Fetching node ==> Downloading https://ghcr.io/v2/homebrew/core/node/blobs/sha256:bc3d4077b6fa78 ########################################################################## 100.0% ==> Installing dependencies for node: brotli, c-ares, icu4c@77, libnghttp2, libnghttp3, libngtcp2, libuv, simdjson, sqlite, uvwasi, lz4, xz and zstd ==> Installing node dependency: brotli ==> Downloading https://ghcr.io/v2/homebrew/core/brotli/manifests/1.2.0 Already downloaded: /Users/mac/Library/Caches/Homebrew/downloads/43040be3ccb15626fbea32e35b07134720b9790ad66caf27be03edac1dfbfeb2--brotli-1.2.0.bottle_manifest.json ==> Pouring brotli--1.2.0.sonoma.bottle.tar.gz /usr/local/Cellar/brotli/1.2.0: 33 files, 1.8MB ==> Installing node dependency: c-ares ==> Downloading https://ghcr.io/v2/homebrew/core/c-ares/manifests/1.34.5-1 Already downloaded: /Users/mac/Library/Caches/Homebrew/downloads/c52b1c91460667312755a235f78ac192a45bff39befbba6da9aa72a17263c559--c-ares-1.34.5-1.bottle_manifest.json ==> Pouring c-ares--1.34.5.sonoma.bottle.1.tar.gz /usr/local/Cellar/c-ares/1.34.5: 176 files, 945.3KB ==> Installing node dependency: icu4c@77 ==> Downloading https://ghcr.io/v2/homebrew/core/icu4c/77/manifests/77.1 Already downloaded: /Users/mac/Library/Caches/Homebrew/downloads/35ec2c3adb94255ba47424a4334da9616d97e1ec6d59ed907b368535018bed0a--icu4c@77-77.1.bottle_manifest.json ==> Pouring icu4c@77--77.1.sonoma.bottle.tar.gz /usr/local/Cellar/icu4c@77/77.1: 277 files, 80MB ==> Installing node dependency: libnghttp2 ==> Downloading https://ghcr.io/v2/homebrew/core/libnghttp2/manifests/1.68.0 Already downloaded: /Users/mac/Library/Caches/Homebrew/downloads/16e7ebe81106c5b0b363cf16b9a25118a344811cd317e5042943682b17675a76--libnghttp2-1.68.0.bottle_manifest.json ==> Pouring libnghttp2--1.68.0.sonoma.bottle.tar.gz /usr/local/Cellar/libnghttp2/1.68.0: 14 files, 735.9KB ==> Installing node dependency: libnghttp3 ==> Downloading https://ghcr.io/v2/homebrew/core/libnghttp3/manifests/1.12.0 Already downloaded: /Users/mac/Library/Caches/Homebrew/downloads/870c7405e7536d3964d6a4063f552f6ba7db08a1057381685a9f9c177df71c9f--libnghttp3-1.12.0.bottle_manifest.json ==> Pouring libnghttp3--1.12.0.sonoma.bottle.tar.gz /usr/local/Cellar/libnghttp3/1.12.0: 20 files, 554.3KB ==> Installing node dependency: libngtcp2 ==> Downloading https://ghcr.io/v2/homebrew/core/libngtcp2/manifests/1.17.0 Already downloaded: /Users/mac/Library/Caches/Homebrew/downloads/f9ac96017064e1c9c23c32050e1fedb487cd3f6a744fc6c8bfd3a3ee8fa90605--libngtcp2-1.17.0.bottle_manifest.json ==> Pouring libngtcp2--1.17.0.sonoma.bottle.tar.gz /usr/local/Cellar/libngtcp2/1.17.0: 21 files, 1.2MB ==> Installing node dependency: libuv ==> Downloading https://ghcr.io/v2/homebrew/core/libuv/manifests/1.51.0-1 Already downloaded: /Users/mac/Library/Caches/Homebrew/downloads/3134253b57ab9327739c97027f8b90160da109e06dda0dc4d2d222a6df0ab9b8--libuv-1.51.0-1.bottle_manifest.json ==> Pouring libuv--1.51.0.sonoma.bottle.1.tar.gz /usr/local/Cellar/libuv/1.51.0: 34 files, 1.2MB ==> Installing node dependency: simdjson ==> Downloading https://ghcr.io/v2/homebrew/core/simdjson/manifests/4.2.1 Already downloaded: /Users/mac/Library/Caches/Homebrew/downloads/346ea6428cf23cfe5c9cf9aa74ba48ce2cf6858f68b5287036d6b8bb09ab76ef--simdjson-4.2.1.bottle_manifest.json ==> Pouring simdjson--4.2.1.sonoma.bottle.tar.gz /usr/local/Cellar/simdjson/4.2.1: 17 files, 6.4MB ==> Installing node dependency: sqlite ==> Downloading https://ghcr.io/v2/homebrew/core/sqlite/manifests/3.51.0 Already downloaded: /Users/mac/Library/Caches/Homebrew/downloads/8465785061e36b7a1fc885b00fc23949c696b13d8b9569ea685ae294b6f57fd4--sqlite-3.51.0.bottle_manifest.json ==> Pouring sqlite--3.51.0.tahoe.bottle.tar.gz /usr/local/Cellar/sqlite/3.51.0: 13 files, 4.9MB ==> Installing node dependency: uvwasi ==> Downloading https://ghcr.io/v2/homebrew/core/uvwasi/manifests/0.0.23-1 Already downloaded: /Users/mac/Library/Caches/Homebrew/downloads/d9fc39e8e8eb3c4e33b14bafb8f46ce7c30a8814a9d2ff809f4a27525ec96893--uvwasi-0.0.23-1.bottle_manifest.json ==> Pouring uvwasi--0.0.23.sonoma.bottle.1.tar.gz /usr/local/Cellar/uvwasi/0.0.23: 15 files, 257.0KB ==> Installing node dependency: lz4 ==> Downloading https://ghcr.io/v2/homebrew/core/lz4/manifests/1.10.0-1 Already downloaded: /Users/mac/Library/Caches/Homebrew/downloads/8e11e90eb21a06e0f199af9d80e011e3693c77dd353b2477579d95c8471a5802--lz4-1.10.0-1.bottle_manifest.json ==> Pouring lz4--1.10.0.tahoe.bottle.1.tar.gz /usr/local/Cellar/lz4/1.10.0: 24 files, 696.2KB ==> Installing node dependency: xz ==> Downloading https://ghcr.io/v2/homebrew/core/xz/manifests/5.8.1 Already downloaded: /Users/mac/Library/Caches/Homebrew/downloads/86a115cc1d43ff8a480fd907f812e70a403e1675d8a7223f61bbb08cbd2adc27--xz-5.8.1.bottle_manifest.json ==> Pouring xz--5.8.1.tahoe.bottle.tar.gz /usr/local/Cellar/xz/5.8.1: 96 files, 2.3MB ==> Installing node dependency: zstd ==> Downloading https://ghcr.io/v2/homebrew/core/zstd/manifests/1.5.7-1 Already downloaded: /Users/mac/Library/Caches/Homebrew/downloads/14f45413747fef87558cd195b1104e55d9739f9574f146051dbd6569ded74a94--zstd-1.5.7-1.bottle_manifest.json ==> Pouring zstd--1.5.7.tahoe.bottle.1.tar.gz /usr/local/Cellar/zstd/1.5.7: 32 files, 2.4MB ==> Installing node ==> Pouring node--25.1.0_1.sonoma.bottle.tar.gz /usr/local/Cellar/node/25.1.0_1: 2,269 files, 78.4MB ==> Running `brew cleanup node`... Disable this behaviour by setting `HOMEBREW_NO_INSTALL_CLEANUP=1`. Hide these hints with `HOMEBREW_NO_ENV_HINTS=1` (see `man brew`). ==> Caveats zsh completions have been installed to: /usr/local/share/zsh/site-functions开始运行 expo 工程：npx create-expo-app@latestexpo 工程是现在 rn 推荐的创建 app 的方式，他的演进经历了如下过程：输入工程名字，可以看到如下结果：打开目录，可以看到如下结构：其中 app 目录是我们的工作目录：对这个文件的介绍：_layout.tsx​ 是各级页面的容器或导航控制器，控制着子页面的呈现方式（是堆叠、标签还是模态）。其他 .tsx文件就是具体的页面内容，相当于 UIViewController。index.tsx​ 是一个特殊文件，它代表所在目录的默认页面（路径为 /）。集成现有项目更改项目目录rn 的目录遵循一定的结构，我们最好按他的约定来组织目录：masterboy git:(master) ✗ tree -I 'node_modules|.git' -L 2 -a . ├── .gitee │ ├── ISSUE_TEMPLATE.zh-CN.md │ └── PULL_REQUEST_TEMPLATE.zh-CN.md ├── .gitignore ├── .vscode │ └── settings.json ├── .xcode.env ├── .xcode.env.local ├── ios │ ├── .DS_Store │ ├── .xcode.env │ ├── .xcode.env.local │ ├── bin │ ├── build │ ├── build_info │ ├── cache │ ├── doc │ ├── extensions │ ├── Gemfile │ ├── Gemfile.lock │ ├── gems │ ├── LICENSE │ ├── MasterBoy │ ├── MasterBoy.xcodeproj │ ├── MasterBoy.xcworkspace │ ├── Podfile │ ├── Podfile.lock │ ├── Pods │ ├── README.en.md │ ├── README.md │ └── specifications ├── package-lock.json └── package.json参考官方教程：Integration with Existing Apps 即可。前置工作下载 package.json 并运行 npm install 安装脚手架。curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.82-stable/template/package.json % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1171 100 1171 0 0 34 0 0:00:34 0:00:33 0:00:01 311然后：masterboy git:(master) ✗ npm install npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. npm warn deprecated @humanwhocodes/config-array@0.13.0: Use @eslint/config-array instead npm warn deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported npm warn deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead npm warn deprecated eslint@8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other options. added 835 packages, and audited 836 packages in 4m 158 packages are looking for funding run `npm fund` for details found 0 vulnerabilities管理 ruby 版本先下载：masterboy git:(master) curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.82-stable/template/Gemfile % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 510 100 510 0 0 93 0 0:00:05 0:00:05 --:--:-- 109pod install再执行：bundle install bundle exec pod install当前项目中集成 React Native最重要的一步来了，要把 RN 集成到我们项目中。链接 RN 和 我们项目肯定就是修改 Podfile 无疑了。思路是：我们直接从 expo 中拿一个模板来即可。在之前的从 0 到 1 生成的 RN 工程中，我们使用了工具链 expo，这次我们仍然使用 expo 让刚才的项目生成 iOS 目录：npx expo prebuild执行该命令后，会生成一个 iOS 项目，我们看一下他的 podfile，然后直接拷贝过来，用到我们原先的群管家中：# Resolve react_native_pods.rb with node to allow for hoisting require Pod::Executable.execute_command('node', ['-p', 'require.resolve( "react-native/scripts/react_native_pods.rb", {paths: [process.argv[1]]}, )', __dir__]).strip platform :ios, min_ios_version_supported prepare_react_native_project! target 'MasterBoy' do config = use_native_modules! # Use static frameworks for React Native compatibility use_frameworks! :linkage => :static use_react_native!( :path => config[:reactNativePath], # An absolute path to your application root. :app_path => "#{Pod::Config.instance.installation_root}/..", # Enable Fabric (New Architecture) :fabric_enabled => true, # Enable Hermes :hermes_enabled => true ) pod 'SnapKit','5.6.0' pod 'YYText','1.0.7' pod 'FDFullscreenPopGesture','1.1' pod 'Toast-Swift', '5.0.1' pod 'Alamofire','5.6.4' pod 'SwiftyJSON','5.0.1' pod 'MJRefresh', '3.7.5' pod 'JLRoutes', '2.1' pod 'LGAlertView' pod 'NVActivityIndicatorView' pod 'SDCycleScrollView', '1.82' pod 'RxSwift', '6.5.0' pod 'RxCocoa', '6.5.0' # Add the Firebase pod for Google Analytics pod 'ReachabilitySwift' pod 'Kingfisher', '7.8.0' pod 'LookinServer', :subspecs => ['Swift'], :configurations => ['Debug'] pod 'CocoaLumberjack','3.8.1' # Pods for MasterBoy pod 'TZImagePickerController/Basic' # No location code pod 'TPNS-iOS','1.4.0.1' pod 'GBDeviceInfo', '~> 6.0' post_install do |installer| react_native_post_install( installer, config[:reactNativePath], :mac_catalyst_enabled => false, # :ccache_enabled => true ) end end 增加的部分大概意思就是引入 React Native 库，接着，我们执行 pod install，就发现 pod 工程中多了很多和 RN 相关的库：运行 RN 项目我们找一个文件，来写 RN 相关的代码：// // MBDReactNativeViewController.swift // MasterBoy // // Created by Claude on 2025/11/13. // // 在文件顶部添加 #if compiler(>=5.9) #warning("RCTRootView is deprecated but still recommended for Brownfield apps in RN 0.82") #endif import UIKit import React class MBDReactNativeViewController: UIViewController, RCTBridgeDelegate { private var bridge: RCTBridge? private var rootView: RCTRootView? override func viewDidLoad() { super.viewDidLoad() // 设置导航栏 self.title = "React Native" self.view.backgroundColor = .white // 加载 React Native 视图 loadReactNativeView() } private func loadReactNativeView() { // 创建 bridge（使用新架构） bridge = RCTBridge(delegate: self, launchOptions: nil) // 创建 RCTRootView rootView = RCTRootView( bridge: bridge!, moduleName: "MasterBoyRN", initialProperties: nil ) // 设置 rootView 的frame if let rootView = rootView { rootView.frame = self.view.bounds rootView.autoresizingMask = [.flexibleWidth, .flexibleHeight] // 添加到视图层级 self.view.addSubview(rootView) } } // MARK: - RCTBridgeDelegate func sourceURL(for bridge: RCTBridge) -> URL? { return getBundleURL() } private func getBundleURL() -> URL? { #if DEBUG // 开发模式：从 Metro bundler 加载 // 确保 Metro bundler 正在运行 (npm start) return RCTBundleURLProvider.sharedSettings().jsBundleURL( forBundleRoot: "index" ) #else // 生产模式：从应用 bundle 加载 // 需要先构建 JavaScript bundle return Bundle.main.url(forResource: "main", withExtension: "jsbundle") #endif } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 隐藏导航栏（可选） // self.navigationController?.setNavigationBarHidden(false, animated: animated) } } 运行后，可以发现文件工程跑起来了：总结RN 看起来麻烦，其实你只要懂原理，还是很简单的。