Posts

Showing posts with the label React Native

A New Collection of Thoughtful Learning Apps — Now Available on iOS & Android

Image
I’m excited to share a set of mobile apps I’ve recently completed and published on both the Google Play Store and the Apple App Store. These apps are designed with a simple goal in mind: to make meaningful, structured content more accessible, whether you’re studying theology or improving your English vocabulary. 📱 Now Available on Both Platforms All apps are live and available for download: Google Play Developer Page: https://play.google.com/store/apps/dev?id=5835943159853189043 Apple App Store Developer Page: https://apps.apple.com/ca/developer/q-z-l-corp/id1888794100 📖 Theology & Confession Study Apps For those interested in Reformed theology and classical Christian teachings, I’ve developed a series of apps that present foundational texts in a clean, focused reading format: The Belgic Confession Canons of Dort Heidelberg Catechism Westminster Shorter Catechism Each app is designed to provide a distraction-free experience, making it easier to read, reflect, and revisit these im...

React Native iOS 修复:MaterialIcons 显示 “?”(字体未加载问题完整解决方案)

Image
React Native iOS 修复:MaterialIcons 显示 “?”(字体未加载问题完整解决方案) 如果你的 React Native 应用在 iOS 上显示 ? 而不是 MaterialIcons 图标,通常是因为 iOS 没有正确加载图标字体导致的。 本文将讲解: 问题出现的原因 完整修复方法 常见坑:Multiple commands produce MaterialIcons.ttf 问题现象 你可能在代码中使用: import MaterialIcons from '@react-native-vector-icons/material-icons'; 并这样渲染图标: <MaterialIcons name="dashboard" size={24} color="#2563eb" /> 但在 iOS 上出现: 显示 ? 图标为空白 图标无法显示 根本原因 问题的核心是 MaterialIcons.ttf 没有被正确加载到 iOS App Bundle 中。 在 iOS 中,字体必须满足: 被加入 App 资源文件 在 Info.plist 中注册 如果缺少任何一步,iOS 就无法渲染字体图标,只会显示 ? 。 解决方案(推荐做法) 第一步:在 Info.plist 注册字体 打开文件: ios/<YourAppName>/Info.plist 添加以下内容: <key>UIAppFonts</key> <array> <string>MaterialIcons.ttf</string> </array> 如果已经存在 UIAppFonts ,只需追加: <string>MaterialIcons.ttf</string> 第二步:清理并重新构建 iOS 项目 修改 Info.plist 后必须重新编译 App。 方法一:Xcode Product → Clean Build F...

React Native iOS Fix: MaterialIcons Showing “?” (Font Not Loaded) – Complete Guide

Image
React Native iOS Fix: MaterialIcons Showing “?” (Font Not Loaded) – Complete Guide If your React Native app is showing ? instead of MaterialIcons on iOS, the issue is almost always caused by a missing or unregistered icon font in the iOS build. This guide explains: Why this happens How to fix it properly How to avoid the common “Multiple commands produce MaterialIcons.ttf” error Symptoms You are using: import MaterialIcons from '@react-native-vector-icons/material-icons'; And rendering icons like: <MaterialIcons name="dashboard" size={24} color="#2563eb" /> But on iOS, you see: A ? instead of icons Blank icons Or missing glyphs Root Cause The issue happens because MaterialIcons.ttf is not properly loaded in the iOS app bundle. On iOS, fonts must be: Included in the app resources Registered in Info.plist If either step is missing, iOS cannot render the icon font and falls back to ? . Fix...

React Native TTS iOS 问题全解析:修复 BOOL 错误与事件监听失效(2026 实战指南)

Image
React Native TTS iOS 问题全解析:修复 BOOL 错误与事件监听失效(2026 实战指南) 在 React Native 中使用文本转语音(TTS)本来很简单,但在 iOS 上却可能踩坑。 本文总结了两个非常常见但又很隐蔽的问题,并提供经过验证的解决方案。 🧨 问题一:Objective-C type BOOL is unsupported 错误信息 TextToSpeech.setDefaultRate(): Error while converting JavaScript argument to Objective C type BOOL convert javascript argument to object C type Bool object C type bool is unsupported 🔍 根本原因 这 不是你的代码问题 。 这是由于 iOS 原生桥接层(Objective-C)类型定义错误导致的,尤其在 React Native 新架构(Fabric / TurboModules)下更容易触发。 部分版本的 react-native-tts 错误地使用了: (BOOL *)onWordBoundary ❌ 错误 而 React Native bridge 不支持 BOOL 指针类型 ,只支持: BOOL NSNumber * ✅ 解决方案 https://github.com/ak1394/react-native-tts/issues/291 使用已修复的 fork 版本: @iternio/react-native-tts npm install @iternio/react-native-tts 该版本已修复 iOS 类型问题,可以正常运行。 ⚠️ 问题二:事件监听器未注册 警告信息 Sending `tts-start` with no listeners registered. 即使你已经写了监听: Tts.addEventListener('tts-start', () => { setIsSpeaking(true); }); 🔍 根本原因 问题在于: ...

解决 React Native iOS 缺少 iPad 图标错误(152x152 / 167x167 验证失败)

Image
解决 React Native iOS 缺少 iPad 图标错误(152x152 / 167x167) 在提交 React Native iOS 应用到 App Store 时,如果你遇到类似错误: Missing required icon file. The bundle does not contain an app icon for iPad of exactly '152x152' pixels The bundle does not contain an app icon for iPad Pro of exactly '167x167' pixels 这个问题看起来很奇怪,因为你的 Xcode 项目中已经显示支持 iPad。 🔍 现象 你可能已经看到: Deployment Info 中有 iPad 配置 iPad Orientation 已启用 但是打开 Assets.xcassets → AppIcon 时: ❌ 没有 iPad 图标槽位 最终导致 App Store 校验失败。 🧠 根本原因 这是因为配置不一致导致的: 项目设置支持 iPad ✅ AppIcon 资源仍然是 iPhone-only ❌ 在很多 React Native 项目中,默认生成的 AppIcon 并不包含 iPad 图标槽位。 ✅ 解决方案(最简单有效) 重新创建 AppIcon: 打开 Assets.xcassets 删除当前的 AppIcon 右键 → New App Icon 命名为 AppIcon 新的 AppIcon 会自动包含: iPad 图标(152x152) iPad Pro 图标(167x167) 🖼️ 必须提供的图标 你至少需要提供: 152 × 152(iPad) 167 × 167(iPad Pro) 将对应 PNG 图片拖入即可。 ⚠️ 重要检查 确保项目确实支持 iPad: Build Settings → Targeted Device Family = 1,2 含义: 1 = iPhone 2 ...

Fix Missing iPad App Icon in React Native iOS (Xcode Validation Error 152x152 / 167x167)

Image
Fix Missing iPad App Icon in React Native iOS (Xcode Validation Error) If you're submitting a React Native iOS app and encounter errors like: Missing required icon file. The bundle does not contain an app icon for iPad of exactly '152x152' pixels The bundle does not contain an app icon for iPad Pro of exactly '167x167' pixels This issue can be confusing — especially when your project already shows iPad support in Xcode. 🔍 The Confusing Part In Xcode, you may already see: iPad orientation settings enabled Deployment Info showing iPhone + iPad However, when opening Assets.xcassets → AppIcon , there are no iPad icon slots . This leads to App Store validation failure. 🧠 Root Cause This is caused by a mismatch between: Xcode project settings (which support iPad) Asset catalog configuration (which may still be iPhone-only) In many React Native projects, the default AppIcon set is created without iPad slots, even when the app later ...

解决 Xcode 报错:Sandbox rsync “Operation not permitted”(React Native / CocoaPods 完整方案)

Image
解决 Xcode 报错:Sandbox rsync “Operation not permitted”(React Native / CocoaPods) 在使用 React Native 开发 iOS 应用时,如果你在 Xcode 中遇到类似如下错误: Sandbox: rsync deny(1) file-read-data Operation not permitted PhaseScriptExecution [CP] Embed Pods Frameworks 那么你踩到了 Xcode 15+ 中一个非常常见的坑。 🔍 问题原因 Xcode 15 引入了更严格的安全机制 —— User Script Sandboxing(用户脚本沙箱) 。 这个机制会限制构建过程中脚本的文件访问权限,而 CocoaPods 在编译时会执行一个脚本(Embed Pods Frameworks),使用 rsync 来复制 framework: ❌ 无法读取 framework 文件(如 React.framework) ❌ 无法写入 app bundle 最终导致 Operation not permitted 错误。 ✅ 解决方案(最有效) 关闭 Xcode 的 User Script Sandboxing : 打开 Xcode 选择你的 Project(不是 Target) 进入 Build Settings 搜索: User Script Sandboxing 将其设置为: NO 然后执行清理并重新编译: Shift + Command + K 通常问题会立刻解决。 💡 原理说明 关闭脚本沙箱后,CocoaPods 的构建脚本将可以正常执行: 读取 framework 文件 复制到应用目录 保留签名信息(CodeSignature) ⚠️ 如果仍然报错(补充方案) 可以尝试以下操作: 给 Xcode 添加 Full Disk Access(完整磁盘权限) 删除 DerivedData 目录 重新执行 pod install 🚀 总结 这个问题并不是你的项目配置错误,而是: Xcode ...

Fix Xcode Sandbox rsync “Operation not permitted” Error (React Native / CocoaPods Solution)

Image
Fix Xcode Sandbox rsync “Operation not permitted” Error (React Native / CocoaPods) If you are building a React Native iOS app and suddenly see errors like: Sandbox: rsync deny(1) file-read-data Operation not permitted PhaseScriptExecution [CP] Embed Pods Frameworks You are not alone. This issue is very common in Xcode 15+ due to stricter sandboxing rules. 🔍 Root Cause Xcode introduced User Script Sandboxing , which restricts scripts (like CocoaPods' framework embedding step) from accessing certain files. During build, rsync is used to copy frameworks (e.g. React.framework), but the sandbox blocks it: ❌ Cannot read framework files ❌ Cannot write into app bundle This results in the infamous Operation not permitted error. ✅ Solution (Works Instantly) Disable User Script Sandboxing in Xcode: Open your project in Xcode Select the project (not target) Go to Build Settings Search for: User Script Sandboxing Set it to: NO Then clean and r...

How I Set Up My Local Environment to Run a React Native iOS App

Image
How I Set Up My Local Environment to Run a React Native iOS App Setting up a React Native project for iOS locally sounds simple—until you hit the usual roadblocks: Ruby versions, CocoaPods issues, Xcode configuration, and mysterious build failures. Here’s a clean, real-world setup that actually works. 🍎 Step 0 — Prepare Xcode (Critical but Easy to Miss) Even if you already installed Xcode from the App Store, your system may not be fully configured for command-line builds. I ran into issues until I completed these steps: 1. Select the Correct Xcode Path sudo xcode-select -s /Applications/Xcode.app/Contents/Developer xcode-select -p Expected output: /Applications/Xcode.app/Contents/Developer 2. Accept the Xcode License sudo xcodebuild -license Then: Press space to scroll through the license Type agree at the end Without this, builds may fail silently or with confusing errors. 3. Install Command Line Tools (if not already) xcode-select --install React Native i...

解决 React Native Android Gradle 构建错误的经验分享

Image
解决 React Native Android Gradle 构建错误的经验分享 最近在开发 React Native Android 项目时,遇到了顽固的 Gradle 构建错误,主要集中在插件解析和本地构建缓存缺失等问题,比如 com.facebook.react.settings 和 foojay-resolver 相关报错。 问题表现 执行 Gradle clean 时提示插件解析失败 本地构建产物缺失或损坏 报错涉及 metadata.bin 和 FoojayToolchainsPlugin 解决步骤 停止所有正在运行的 Gradle 进程: ./gradlew stop 删除本地 native 构建缓存: rm -rf .cxx 清理并重新构建项目,同时刷新依赖: ./gradlew clean build --refresh-dependencies 最终效果 按照上述步骤操作后,构建顺利通过,所有插件和本地依赖相关错误都被解决。如果你也遇到类似问题,不妨试试这套方法!

How I Fixed React Native Android Gradle Build Errors

Image
How I Fixed React Native Android Gradle Build Errors Recently, I encountered persistent Gradle build errors while working on a React Native Android project. The errors were related to plugin resolution and missing native build artifacts, such as com.facebook.react.settings and foojay-resolver . Symptoms Gradle clean failed with plugin resolution errors Native build artifacts missing or corrupted Errors referencing metadata.bin and FoojayToolchainsPlugin Solution Steps Stop all running Gradle daemons: ./gradlew stop Delete the native build cache: rm -rf .cxx Clean and rebuild the project with refreshed dependencies: ./gradlew clean build --refresh-dependencies Result After these steps, the build succeeded and all plugin and native dependency errors were resolved. If you encounter similar issues, try this sequence before diving into more complex troubleshooting!

React Native 导航模式:为共享页面使用全局 Stack

Image
React Native 导航模式:为共享页面使用全局 Stack 在许多 React Native 应用中,你可能希望从多个 Tab 打开同一个页面(如 Article 或 Details ),并且希望返回按钮能回到正确的 Tab。如果你只是把页面放在某个 Tab 的 Stack 里,会遇到一个常见的 UX 问题:返回按钮总是回到该 Stack 的根页面,而不是你来时的 Tab。 问题描述 假设你有一个包含 Home 、 Study 和 Mastery 的 Tab Navigator。如果你把 ArticleScreen 放在 Home 的 Stack 里,并从 Study 或 Mastery 跳转到它,返回按钮总是回到 Home ,而不是你来时的 Tab。这是因为导航栈是 Tab 局部的。 解决方案:使用全局 Stack 最佳实践是创建一个 RootStack ,把 Tab Navigator 和所有共享页面包裹起来。这样,任何 Tab 都可以 push 共享页面,返回按钮会回到正确的 Tab。 步骤 1:定义 Root Stack import { createNativeStackNavigator } from '@react-navigation/native-stack'; import TabNavigator from './TabNavigator'; import ArticleScreen from './ArticleScreen'; const RootStack = createNativeStackNavigator(); export default function AppNavigator() { return ( <RootStack.Navigator> <RootStack.Screen name=\"Main\" component={TabNavigator} options={{ headerShown: false }} /> <Roo...

React Native Navigation Pattern: Global Stack for Shared Screens

Image
React Native Navigation Pattern: Global Stack for Shared Screens In many React Native apps, you’ll want to open a screen (like an Article or Details page) from multiple tabs, and have the back button return to the correct previous tab. If you simply nest your screen inside a stack for one tab, you’ll run into a common UX issue: the back button always returns to the root of that stack, not to the tab you came from. The Problem Suppose you have a tab navigator with Home , Study , and Mastery tabs. If you put ArticleScreen inside the Home stack, and navigate to it from Study or Mastery , the back button will always return to Home —not the tab you came from. This is because the navigation stack is local to the tab. The Solution: Use a Global Stack The best practice is to create a RootStack that wraps your tab navigator and any shared screens. This way, any tab can push the shared screen, and the back button will return to the correct previous tab...

Fix Android Emulator “Not Enough Space” Error (installDebug Failed)

Image
Fix Android Emulator “Not Enough Space” Error (installDebug Failed) If you are running a React Native app and see this error when executing npm run android , you are not alone. Execution failed for task ':app:installDebug'. ... java.io.IOException: Requested internal only, but not enough space This error usually means one thing: 🚨 Your Android Emulator is out of storage 💡 Root Cause By default, Android Virtual Devices (AVD) are created with very limited internal storage (often 2GB–6GB). Over time, this space gets filled by: Debug APK installs Gradle build artifacts System updates and cache Eventually, there is no space left to install your app. ✅ My Fix (Works Immediately) The most effective solution is to increase the emulator storage size. Open Android Studio Go to Device Manager Edit your emulator (or create a new one) Click Show Advanced Settings Set Internal Storage to 16 GB Save and restart the emulator After inc...

解决 Android 模拟器空间不足导致 installDebug 失败问题

Image
解决 Android 模拟器空间不足导致 installDebug 失败问题 如果你在运行 npm run android 时遇到以下错误: Execution failed for task ':app:installDebug'. ... java.io.IOException: Requested internal only, but not enough space 那么问题通常很简单: 🚨 Android 模拟器空间不足 💡 问题原因 Android 虚拟设备(AVD)默认的内部存储空间通常只有 2GB–6GB,很容易被占满: 多次安装 Debug APK Gradle 构建缓存 系统更新和缓存文件 最终导致无法再安装应用。 ✅ 我的解决方法(最有效) 直接扩大模拟器存储空间: 打开 Android Studio 进入 Device Manager 编辑已有模拟器或创建新模拟器 点击 Show Advanced Settings 将 Internal Storage 设置为 16 GB 保存并重启模拟器 设置为 16GB 后,问题即可彻底解决。 ⚡ 临时解决方案 如果只是临时应急,可以: 清空模拟器数据(Wipe Data) 手动卸载应用: adb uninstall your.package.name 但这些只是短期解决方案。 🧠 开发建议 开发环境建议至少分配 12GB–16GB 存储 关闭 Snapshot(避免保存“满磁盘状态”) 定期清理构建: cd android ./gradlew clean ✅ 总结 如果看到错误: Requested internal only, but not enough space 这 不是代码问题 ,而是模拟器磁盘空间不足。 根本解决方案: 将 AVD 内部存储提升到 16GB。 这是最稳定、最彻底的解决办法。

解决 React Native Modal 中 ScrollView 无法滚动的问题(最佳 Modal 结构)

Image
解决 React Native Modal 中 ScrollView 无法滚动的问题(最佳 Modal 结构) 在使用 React Native 开发应用时,一个很常见的问题是: 在 Modal 组件中放入 ScrollView , 虽然滚动条显示出来了,但内容却无法正常滚动。 很多开发者会发现,Modal 打开后 ScrollView 看起来是可以滚动的, 但是手指滑动时内容却几乎不动,或者滚动非常困难。 这个问题通常是因为 Modal 的 Overlay 层拦截了触摸事件 。 如果 Overlay 使用 TouchableOpacity 或 Pressable 并包裹整个 Modal 内容, 那么滚动手势会被 Overlay 捕获,从而导致 ScrollView 无法接收到滚动事件。 问题示例 很多项目中的 Modal 结构通常像这样: <TouchableOpacity style={styles.overlay} onPress={onClose}> <TouchableOpacity style={styles.modal}> <ScrollView> ... </ScrollView> </TouchableOpacity> </TouchableOpacity> 在这种结构下,最外层的 TouchableOpacity 会捕获触摸手势。当用户尝试滚动时, 触摸事件会先被 Overlay 处理,从而阻止 ScrollView 的滚动行为。 结果就是: 滚动条存在,但滚动不流畅甚至无法滚动。 正确的 Modal 结构模式 正确的解决方案是: 不要用 Touchable 包裹整个 Modal , 而是将 背景点击区域 与 Modal 内容区域 分离。 我们可以在背景上放一个独立的 Pressable, 用于点击关闭 Modal,而 Modal 内容本身保持普通 View。 <Modal visible={visible} transparent animationType="fade" onRequestClose={onC...

Fix React Native Modal ScrollView Not Scrolling (Best Modal Pattern)

Image
Fix React Native Modal ScrollView Not Scrolling (Best Modal Pattern) A common issue when building modals in React Native is that a ScrollView inside a Modal appears scrollable but does not actually scroll smoothly. The scrollbar may appear, but gestures don't move the content properly. This usually happens because the modal overlay is intercepting touch events. If the overlay is implemented using TouchableOpacity or Pressable wrapped around the modal content, it can capture scroll gestures before they reach the ScrollView . In this post, we'll look at the problem and the correct modal pattern used in production React Native apps. The Problem Many developers structure their modal like this: <TouchableOpacity style={styles.overlay} onPress={onClose}> <TouchableOpacity style={styles.modal}> <ScrollView> ... </ScrollView> </TouchableOpacity> </TouchableOpacity> The outer TouchableOpacity captures ...

解决 react-native-tts Android 构建失败:Could not find method jcenter()

Image
解决 react-native-tts Android 构建失败:Could not find method jcenter() 在运行 React Native Android 项目时,我遇到了如下构建错误: A problem occurred evaluating project ':react-native-tts'. > Could not find method jcenter() for arguments [] on repository container of type 错误发生在执行以下命令时: ./gradlew app:installDebug 根据错误信息,问题最终定位到了以下文件: node_modules/react-native-tts/android/build.gradle 问题原因分析 jcenter() 已经被 Gradle 官方弃用,并在较新的 Gradle 版本中被移除。 但部分较老的 React Native 第三方库仍然在 Android 配置中使用 jcenter() ,这会直接导致 Android 构建失败。 本次出问题的正是 react-native-tts 这个库。 为什么不能直接改 node_modules? 直接修改 node_modules 中的代码虽然可以暂时解决问题,但并不可靠。 以下操作都会导致修改丢失: 重新执行 npm install 重新执行 yarn install 删除并重建 node_modules 因此,我们需要一种 可重复、可维护、对团队友好 的解决方案。 正确的解决方案:patch-package patch-package 是一个非常实用的工具,可以让我们对第三方依赖进行补丁修复,并在每次安装依赖时自动应用这些修改。 在 react-native-tts 官方修复之前,这是一个非常稳妥的方案。 修复步骤详解 1. 安装 patch-package npm install patch-package --save-dev 或者使用 Yarn: yarn add patch-package --d...

Fix react-native-tts Android Build Error: Could Not Find Method jcenter()

Image
Fixing react-native-tts Android Build Error: Could Not Find Method jcenter() While running a React Native project on Android, I encountered the following build error: A problem occurred evaluating project ':react-native-tts'. > Could not find method jcenter() for arguments [] on repository container of type The build failed when running: ./gradlew app:installDebug After checking the stack trace, the error clearly pointed to the following file inside node_modules : node_modules/react-native-tts/android/build.gradle Why This Error Happens jcenter() has been deprecated and removed in newer versions of Gradle. However, some older React Native libraries still reference it. In this case, the library react-native-tts was still using jcenter() in its Android Gradle configuration, which caused the build to fail immediately. The Tempting but Wrong Fix You can temporarily fix the issue by directly editing the file inside node_modules — but this so...

WSC QA: Study the Westminster Shorter Catechism | Q.Z.L Corp

Image
WSC QA: Interactive Catechism Learning App By Q.Z.L Team | Published on 2026-01-20 Demo Video Elevator Pitch Deepen your knowledge of the Westminster Shorter Catechism in English & Chinese with a modern app featuring full Q&A, scripture references, quizzes, text-to-speech, and an AI Tutor for guided learning. What it does Complete catechism Q&A in English & Chinese. Full scripture references for every answer. Interactive quiz mode to test knowledge and memorization. Text-to-speech support for auditory learning. AI Tutor Chat powered by Gemini 3 for real-time guidance. Modern interface for smooth browsing and study. Try it now: Web App | Android w/ ads | Android Paid, no ads Inspiration We wanted a modern, interactive, and accessible way to study the Westminster Shorter Catechism. S...

Fix INSTALL_FAILED_UPDATE_INCOMPATIBLE When Installing Android APK via ADB

Image
Fix INSTALL_FAILED_UPDATE_INCOMPATIBLE When Installing Android APK via ADB After building your React Native Android release APK, you may encounter this error when installing it: adb: failed to install app-release.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package signatures do not match newer version] This means the APK was built successfully, but Android refuses to install it because the app on your device was signed with a different certificate. Why This Happens Android requires that any update to an existing app must be signed with the same keystore as the original installation. Typically this happens when: You installed a debug build previously You switched keystores for your release build You changed your signing configuration If the signatures don’t match, Android will block the installation. How to Fix It Option 1: Uninstall the Existing App (Quick Fix) adb uninstall com.westminstershortercatechismqa adb install app-release.apk Onc...