ios – Troubleshooting a react native expo app that crashes on the splash screen on startup


I’ve been working on this react native expo project and I can’t seem to get the production version of my app to launch on iOS. I’ve used prebuild to open the app in xcode and I keep getting warnings regarding safe area view running in the main thread. I could really use a second set of eyes on my packages to see where else I can check. I’m using stack navigator, expo recording microphone, I’m not using notifications either.

PACKAGE.JSON


{
  "name": "vococoapp",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo run:android",
    "ios": "expo run:ios",
    "web": "expo start --web"
  },
  "dependencies": {
    "@expo/vector-icons": "^13.0.0",
    "@react-native-community/masked-view": "^0.1.11",
    "@react-native-masked-view/masked-view": "^0.2.9",
    "@react-navigation/native": "^6.1.7",
    "@react-navigation/stack": "^6.3.17",
    "expo": "^49.0.21",
    "expo-application": "~5.3.0",
    "expo-av": "~13.4.1",
    "expo-constants": "~14.4.2",
    "expo-dev-client": "~2.4.12",
    "expo-device": "~5.4.0",
    "expo-file-system": "~15.4.5",
    "expo-splash-screen": "~0.20.5",
    "expo-status-bar": "~1.6.0",
    "expo-updates": "~0.18.17",
    "react": "18.2.0",
    "react-native": "0.72.6",
    "react-native-gesture-handler": "~2.12.0",
    "react-native-paper": "^5.10.1",
    "react-native-reanimated": "~3.3.0",
    "react-native-safe-area-context": "^4.6.3",
    "react-native-screens": "~3.22.0",
    "react-native-svg": "13.9.0",
    "react-native-svg-transformer": "^1.1.0",
    "react-native-uuid": "^2.0.1",
    "sentry-expo": "^7.1.1",
    "styled-components": "^6.0.7"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0"
  },
  "private": true
}

XCODE WARNINGS

/Users/nylandsidifall/Documents/VSCode_Projects/VoCoCo/VoCoCoApp/node_modules/expo-dev-menu/vendored/react-native-safe-area-context/ios/SafeAreaView/DevMenuRNCSafeAreaProviderManager.swift:21 -[UIWindow safeAreaInsets] must be used from main thread only

/Users/nylandsidifall/Documents/VSCode_Projects/VoCoCo/VoCoCoApp/node_modules/expo-dev-menu/vendored/react-native-safe-area-context/ios/SafeAreaView/DevMenuRNCSafeAreaProviderManager.swift:31 UIView.frame must be used from main thread only

/Users/nylandsidifall/Documents/VSCode_Projects/VoCoCo/VoCoCoApp/node_modules/expo-dev-menu/vendored/react-native-safe-area-context/ios/SafeAreaView/DevMenuRNCSafeAreaProviderManager.swift:16 UIApplication.keyWindow must be used from main thread only

/Users/nylandsidifall/Documents/VSCode_Projects/VoCoCo/VoCoCoApp/ios/Pods/SocketRocket/SocketRocket/Internal/RunLoop/SRRunLoopThread.m:79 Thread running at User-interactive quality-of-service class waiting on a lower QoS thread running at Default quality-of-service class. Investigate ways to avoid priority inversions

EXAMPLE MAIN VIEW CODE

 
import MainViewTemplate from "../Templates/MainViewTemplate";
import Logo from "../../assets/VoCoCoLogo.svg";
import React, { useContext, useEffect, useState } from "react";
import { Button, Text, ScrollView } from "react-native";
import { useIsFocused } from "@react-navigation/native";
import { RecordingsContext } from "../../Providers/RecordingContextProvider";
import { Searchbar } from "react-native-paper";

import {
  LogoView,
  SearchbarView,
  RecordingResultsView,
} from "../../Components/Styled-Components/Styled-Components";
import styled from "styled-components";
import { RecordingTagContext } from "../../Providers/RecordingTagContextProvider";
import { SafeAreaView } from "react-native-safe-area-context";

const TagContainer = styled.View`
  flex: 0.17;
  width: 100%;
  padding: 10px;
`;

const RecordResultContainer = styled.View`
  flex: 1;
`;

const TagButton = styled.TouchableOpacity`
  background-color: #f98d00;
  padding: 4px 16px; /* Adjust the padding as needed */
  border-radius: 20px; /* Use a large value for full rounding */
  margin-right: 10px;
  height: 100%;
  display: flex;
  align-items: center; /* Center text vertically */
  justify-content: center;
`;

const ButtonText = styled.Text`
  color: black;
  font-weight: bold;
  flex-wrap: nowrap;
`;

const ScreenWrapper = styled(SafeAreaView)`
  flex: 1;
  background-color: #fff; /* Set your desired background color */
`;

const ContentWrapper = styled.View`
  flex: 1;
  width: 100%;
`;

const MainScreen = ({ navigation }) => {
  const { storedRecordings } = useContext(RecordingsContext);
  const { storedRecordingTags, loadTags } = useContext(RecordingTagContext);

  const isFocused = useIsFocused();

  const [playingSound, setPlayingSound] = useState(null);
  const [searchQuery, setSearchQuery] = useState("");
  const [selectedTag, setSelectedTag] = useState("");

  useEffect(() => {
    if (isFocused) {
      refreshMainScreen();
      loadTags();
    }
  }, [isFocused]);

  const refreshMainScreen = () => {};

  const onChangeSearch = (query) => setSearchQuery(query);

  const getRecordingLines = () => {
    let filteredRecordings = storedRecordings;

    // filter the recordings if a tag is selected
    if (selectedTag) {
      filteredRecordings = storedRecordings.filter((recording) =>
        recording["tag"].includes(selectedTag)
      );
    }

    // filter based on search query
    filteredRecordings = filteredRecordings.filter((recording) =>
      recording["name"].toLowerCase().includes(searchQuery.toLowerCase())
    );

    return filteredRecordings.map((recording, index) => {
      return (
        <RecordingResultsView key={index}>
          <Text>
            {recording["name"]} | {recording["duration"]} | Tag:{" "}
            {recording["tag"]}
          </Text>

          <Button
            onPress={async () => {
              if (playingSound) {
                await playingSound.stopAsync();
              }
              await recording["sound"].replayAsync();
              setPlayingSound(recording["sound"]);
            }}
            title="Play"
          ></Button>

          <Button
            onPress={() => {
              navigation.navigate("replay", { recordingId: recording["id"] });
            }}
            title="Edit"
          ></Button>
        </RecordingResultsView>
      );
    });
  };

  const getTagLines = () => {
    return storedRecordingTags.map((item, index) => (
      <TagButton key={index} onPress={() => setSelectedTag(item)}>
        <ButtonText>{item}</ButtonText>
      </TagButton>
    ));
  };

  return (
    <ScreenWrapper>
      <ContentWrapper>
        <LogoView>
          <Logo width={220} height={90} />
        </LogoView>
        <SearchbarView>
          <Searchbar
            placeholder="Search For Voice"
            onChangeText={onChangeSearch}
            value={searchQuery}
          />
        </SearchbarView>

        <TagContainer>
          <ScrollView horizontal showsHorizontalScrollIndicator={false}>
            {getTagLines()}
          </ScrollView>
        </TagContainer>

        {storedRecordingTags.length > 0 ? (
          <Button
            title="Clear Tag Search"
            onPress={() => {
              setSelectedTag("");
            }}
          />
        ) : (
          <></>
        )}

        <RecordResultContainer>
          <ScrollView showsVerticalScrollIndicator={false}>
            {getRecordingLines()}
          </ScrollView>
        </RecordResultContainer>

        <Button
          title="To New Recording Screen"
          onPress={() => navigation.navigate("recordings")}
        />
      </ContentWrapper>
    </ScreenWrapper>
  );
};

export default MainScreen;

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img