React Native IOS App崩溃,以NULL调用CFRelease()

时间:2018-12-10 08:32:26

标签: react-native

我无法在调试模型中重现该错误。但是在发行版应用程序中,使用react-navigation后退并多次浏览选项卡后,该应用程序崩溃了。我得到了sentry的错误。

应用程序是否因为线程过多而崩溃?每次浏览该标签时,都会有4个http请求。

感谢您的选择。错误如下:

OS Version: iOS 12.1 (16B92)
Report Version: 104

Exception Type: EXC_BREAKPOINT (SIGTRAP)
Crashed Thread: 22

Application Specific Information:
*** CFRelease() called with NULL *** > countByEnumeratingWithState:objects:count: > objectAtIndexedSubscript:

Thread 22 Crashed:
0   CoreFoundation                  0x311d5df20         CFRelease
1   INKubatorApp                    0x202f00d48         _ZN5folly6detail15str_to_integralIxEENS_8ExpectedIT_NS_14ConversionCodeEEEPNS_5RangeIPKcEE
2   CoreFoundation                  0x311e7f600         <redacted>
3   CoreFoundation                  0x311d5d530         <redacted>
4   CoreFoundation                  0x311d5e114         <redacted>
5   INKubatorApp                    0x202e64a24         <redacted>
6   INKubatorApp                    0x202eab7c8         RCTFBQuickPerformanceLoggerConfigureHooks
7   INKubatorApp                    0x202eab524         RCTFBQuickPerformanceLoggerConfigureHooks
8   libdispatch.dylib               0x3113a66c8         <redacted>
9   libdispatch.dylib               0x3113a7484         <redacted>
10  libdispatch.dylib               0x311381fb0         <redacted>
11  libdispatch.dylib               0x311382af4         <redacted>
12  libdispatch.dylib               0x31138af14         <redacted>
13  libsystem_pthread.dylib         0x3117c00dc         _pthread_wqthread

我的导航代码:

<TouchableOpacity onPress={ () => this.props.navigation.navigate('BillList',{ listType: 'investment' }) }>

BillList.js

render(){
        return (
            <View style={ styles.container }>
                <HeaderCom title={ this.getListTitle() }  backgEvent={ () => this.props.navigation.goBack() }/>
                <InvestmentTab screenProps={ this.props.screenProps } />    
            </View>
        )
    }

InvestmentTab.js

const InvestmentTab = createMaterialTopTabNavigator({
    allBills: {
        screen: BillContent,
        navigationOptions: {
            tabBarLabel: I18n.t('investment.all'),
        }
    },
    toBePaidBills: {
        screen: BillContent,
        navigationOptions: {
            tabBarLabel: I18n.t('investment.to_be_paid')
        }
    },
    paidBills: {
        screen: BillContent,
        navigationOptions: {
            tabBarLabel: I18n.t('investment.paid')
        }
    },
    closedBills: {
        screen: BillContent,
        navigationOptions: {
            tabBarLabel: I18n.t('investment.closed')
        }
    },
}, {
    animationEnabled: true,
    tabBarPosition: 'top', // 修改导航的位置
    swipeEnabled: true,
    tabBarOptions: {
        activeTintColor: commonStyle.main, // 选中的颜色
        inactiveTintColor: commonStyle.bill_tab_inactive,
        showIcon: false, // 是否显示小图标
        style: { // 可以设置tab的各种样式
            backgroundColor: commonStyle.white, //底部tab的背景颜色
            height: 56,
            borderBottomWidth: 1,
            borderBottomColor: commonStyle.border_color,
            borderTopWidth: 1,
            borderTopColor: commonStyle.border_color,
            elevation: 0,
            justifyContent: 'space-between'
        },
        labelStyle: {
            fontSize: 14,
            textAlignVertical: 'center',
            paddingTop: 3,
            marginHorizontal: -1,
        },
        indicatorStyle: {
            backgroundColor: commonStyle.main,
            width: Dimensions.get('window').width * .16,
            position: 'absolute',
            left: '4.5%',
        },
        pressOpacity: 0.8,
    }
});

export default InvestmentTab;

BillContent.js只是一个FlatList,我从componentWillMount()的服务器中获取数据。

componentWillMount() {
        appStorage.getUser().then(user => {
            this.setState({ userId: user.user_id });
            this._onRefresh();
            this.props.navigation.addListener('willFocus', this._onRefresh);
        });
    }

在发行版应用程序中,多次返回并导航至一个标签页(该名称是BillList,对不起这个怪异的名字,我很抱歉),该应用程序崩溃了。

1 个答案:

答案 0 :(得分:2)

首先,我认为这是由于过多的http请求和对react-navigation的不正确使用引起的。下面是我的修复代码:

我的导航代码:

<TouchableOpacity onPress={ () => this.props.navigation.navigate('MyTab',{ listType: 'investment' }) }>

MyTab.js,是的,我没有将导航嵌入到名为BillList.js的组件中:

export default createMaterialTopTabNavigator({
    allBills: {
        screen: MyList,
        navigationOptions: {
            tabBarLabel: I18n.t('investment.all'),
        }
    },
    toBePaidBills: {
        screen: MyList,
        navigationOptions: {
            tabBarLabel: I18n.t('investment.to_be_paid')
        }
    },
    paidBills: {
        screen: MyList,
        navigationOptions: {
            tabBarLabel: I18n.t('investment.paid')
        }
    },
    closedBills: {
        screen: MyList,
        navigationOptions: {
            tabBarLabel: I18n.t('investment.closed')
        }
    },
}, {
    animationEnabled: true,
    tabBarPosition: 'top', // 修改导航的位置
    swipeEnabled: true,
    tabBarOptions: {
        // ...
    }
});

MyList.js,我在导航“ didFocus”生活事件中更改了怪异的名称,并仅通过axios请求数据:

componentDidMount() {
        appStorage.getUser().then(user => {
            this.setState({ userId: user.user_id });
            this.props.navigation.addListener('didFocus', this._onRefresh);
        });

    }

其次,我认为这是由于组件卸载后未取消http请求导致的,所以我添加了axios cancelToken。这是代码:

http请求方法:

getOrderArr(type, storage_user_id, page, callback, errCallback, navigation, listType) {
        source = axios.CancelToken.source();
        let that = this;
        var query = this.setRequestData(type, page, listType);
        var resOrderArr = [];
        let config = {cancelToken: source.token};
        InkubatorSApi.send({method: 'GET', url: query.url, obj: query.data, config: config}, (res) => {
            if (axios.isCancel(res)) return;
            // do something
        }, navigation);
    }

MyList.js componentWillUnmount()

componentWillUnmount() {
        source && source.cancel('Operation canceled by the user.');
        this.navigationFocusEvent && this.navigationFocusEvent.remove();
    }

最后,经过相同的操作,我在使用iPhone的调试模式下运行应用程序。 Xcode控制台出现错误:

Assertion failed: (_lock_), function __SCNetworkReachabilityRestartResolver_block_invoke, file /BuildRoot/Library/Caches/com.apple.xbs/Sources/configd/configd-963.200.27/SystemConfiguration.fproj/SCNetworkReachability.c, line 1772.
(lldb)

同时,sentry的HTTP响应状态为0(表示请求无法到达)。这是错误图片链接(我没有足够的声誉来上传图片): error image

因此,我认为这可能是由IOS而非我的代码引起的。谁知道?