# iOS Crash Prevention - Quick Reference **Last Updated**: 2025-11-02 This is a quick reference for common iOS crash patterns and how to prevent them. For the complete debugging journey, see [DEEPLINK_CRASH_FIX.md](./DEEPLINK_CRASH_FIX.md). --- ## 1. LinearGradient Crashes ### ❌ DON'T DO THIS: ```typescript import { LinearGradient } from 'expo-linear-gradient'; const styles = StyleSheet.create({ gradient: { width: '100%', // Can be undefined during navigation! height: 100, } }); ``` **Why it crashes**: During navigation (especially deeplinks), `width: '100%'` can be undefined before parent layout resolves. CoreGraphics crashes trying to render with invalid dimensions. ### ✅ DO THIS INSTEAD: ```typescript const styles = StyleSheet.create({ gradient: { alignSelf: 'stretch', // More reliable than width: '100%' minWidth: 200, // Ensure valid dimensions for CoreGraphics height: 100, } }); ``` **Crash signature**: `CoreGraphics CGContextDrawLinearGradient + 236` --- ## 2. Image Loading During Navigation ### ❌ DON'T DO THIS: ```typescript import { Image } from 'expo-image'; ``` **Why it crashes**: Image transitions can conflict with navigation transitions, causing CoreGraphics to deallocate images while still rendering. ### ✅ DO THIS INSTEAD: ```typescript ``` **Crash signature**: `CoreGraphics image_finalize`, `CA::Layer::~Layer()` --- ## 3. Navigation Snapshots ### ❌ DON'T DO THIS: ```typescript // Missing _layout.tsx in directory app/ └── myfeature/ └── screen.tsx // No layout config! ``` **Why it crashes**: react-native-screens creates snapshots for transitions. Without proper config, snapshots fail on complex views (gradients, blurs, images). ### ✅ DO THIS INSTEAD: ```typescript // app/myfeature/_layout.tsx import { Stack } from 'expo-router'; import { Platform } from 'react-native'; export default function MyFeatureLayout() { return ( ); } ``` **Crash signature**: `RNSScreen setViewToSnapshot`, `snapshotViewAfterScreenUpdates` --- ## 4. Loading Screens During Navigation ### ❌ DON'T DO THIS: ```typescript export default function DeeplinkHandler() { const [loading, setLoading] = useState(true); return loading ? ( // Creates snapshot, then redirects = crash ) : ( ); } ``` **Why it crashes**: Mounting a loading screen that immediately redirects causes snapshot creation mid-navigation. ### ✅ DO THIS INSTEAD: ```typescript export default function DeeplinkHandler() { return ; // Direct redirect, no snapshot } ``` --- ## 5. Component Props ### ❌ DON'T DO THIS: ```typescript // Missing required prop! ``` **Why it crashes**: Component tries to access array with undefined key. ### ✅ DO THIS INSTEAD: ```typescript // Proper context ``` --- ## Code Review Checklist Before merging iOS-related code, verify: - [ ] No `LinearGradient` uses `width: '100%'` or `height: '100%'` - [ ] All `LinearGradient` styles have `minWidth` and/or `minHeight` - [ ] Navigation screens have `transition={0}` on `expo-image` components - [ ] All route directories have `_layout.tsx` with `freezeOnBlur: false` - [ ] No loading screens immediately before `` - [ ] All custom components have required props documented --- ## Testing Requirements Before deploying iOS changes: 1. **Test on physical device** (not just simulator) 2. **Test deeplinks**: Cold start (app closed) and warm start (background) 3. **Test navigation**: Between multiple screens rapidly 4. **Test with slow network**: Enable network conditioning 5. **Check crash logs**: Use Xcode Organizer or TestFlight feedback --- ## Quick Diagnostics ### App crashes during navigation? 1. Check for `LinearGradient` with `width: '100%'` 2. Check for `expo-image` with `transition > 0` 3. Check crash log for "CGContext" or "RNSScreen" ### App crashes on deeplink? 1. Verify route has `_layout.tsx` 2. Check for intermediate loading screens 3. Test with direct `` ### App crashes showing loading screen? 1. Check component has all required props 2. Verify arrays/objects aren't undefined 3. Add null checks before array access --- ## Common Error Messages | Error Message | Likely Cause | Solution | |--------------|--------------|----------| | `CGContextDrawLinearGradient` | LinearGradient invalid dimensions | Use `alignSelf: 'stretch'` + `minWidth` | | `RNSScreen setViewToSnapshot` | Missing Stack config or complex view | Add `_layout.tsx` with `freezeOnBlur: false` | | `image_finalize` | Image deallocated during render | Disable transitions, add recycling key | | `Cannot convert undefined to object` | Missing prop or undefined array | Add required props, null checks | --- ## Resources - [Complete debugging guide](./DEEPLINK_CRASH_FIX.md) - [expo-router docs](https://docs.expo.dev/router/introduction/) - [expo-image transitions](https://docs.expo.dev/versions/latest/sdk/image/) - [react-native-screens](https://github.com/software-mansion/react-native-screens) --- ## Need Help? If you encounter a crash not covered here: 1. **Get the full crash log** from Xcode Organizer or TestFlight 2. **Identify the crash signature** (function names in stack trace) 3. **Document reproduction steps** (exact user actions) 4. **Check recent changes** to navigation or layout code 5. **Add to this document** once resolved!