React-native IOS:网络请求失败

问题描述 投票:0回答:4

我正在测试一个 React Native 应用程序(在 OS X Yosemite 上的 xcode 模拟器 v9.2 / xcode 7.2.1 上)。我在使用以下代码时遇到

Network request failed
错误。具有正确 appid 的实际 url 在浏览器中工作得很好,并以 json 格式提供了正确的信息,并且 Promise / api 调用看起来很好。

我不在防火墙后面。我已尝试对连接进行故障排除,并在开发人员设置中激活

Allow HTTP Services
,但仍然收到错误消息。

知道这里有什么问题吗?实际错误如下:

-- There has been a problem with your fetch operation: Network request failed
-- Api call error =  Network request failed

这是 api.js 代码:

var _ = require('lodash');
var rootUrl = 'http://api.openweathermap.org/data/2.5/weather?APPID=xxxxxxxxxxxxxxxxxxxxxx';

var kelvinToF = function(kelvin) {
  return Math.round((kelvin - 273.15) * 1.8 + 32) + ' ˚F'
};

var kelvinToC = function(kelvin) {
  return Math.round(kelvin - 273.15) + ' ˚C'
};  

module.exports = function(latitude, longitude) {
  var url = `${rootUrl}&lat=${latitude}&lon=${longitude}`;
  console.log(url);
  return fetch(url)
    .then(function(response){
      return response.json();
    })
    .then(function(json){
      return {
        city: json.name,
        temperature1: kelvinToF(json.main.temp),
        temperature2: kelvinToC(json.main.temp),
        description: _.capitalize(json.weather[0].description)
      }
    })
    .catch(function(error) {
    console.log('There has been a problem with your fetch operation: ' + error.message);
    throw error;
});
}

这是index.ios.js代码。

/*  --depreciated

var React = require('react-native'); 

var {
  AppRegistry,
  MapView,
  View,
  Text,
  StyleSheet
} = React;
*/ 


// updated
import React from 'react';

// updated
import {
  AppRegistry,
  MapView,
  View,
  Text,
  StyleSheet,
} from 'react-native';

var Api = require('./src/api');

var Weather = React.createClass({
  getInitialState: function() {
    return {
      pin: {
        latitude: 0,
        longitude: 0
      },
      city: '',
      temperature1: '',
      temperature2: '',
      description: ''
    };
  },
  render: function() {
    return <View style={styles.container}>
      <MapView
        annotations={[this.state.pin]}
        onRegionChangeComplete={this.onRegionChangeComplete}
        style={styles.map}>
      </MapView>
      <View style={styles.textWrapper}>
        <Text style={styles.text}>{this.state.city}</Text>
        <Text style={styles.text}>{this.state.temperature1}</Text>
        <Text style={styles.text}>{this.state.temperature2}</Text>
        <Text style={styles.text}>{this.state.description}</Text>
      </View>
    </View>
  },
  onRegionChangeComplete: function(region) {
    this.setState({
      pin: {
        longitude: region.longitude,
        latitude: region.latitude
      }
    });

    Api(region.latitude, region.longitude)
      .then((data) => {
        console.log(region.latitude);
        console.log(region.longitude);
        console.log('data = ' + data);
        this.setState(data);
      })
      .catch((error)=>{
     console.log("Api call error = ", error.message);
    // alert(error.message);     
  });
  }
});


var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'stretch',
    backgroundColor: '#F5FCFF'
  },
  map: {
    flex: 2,
    marginTop: 30
  },
  textWrapper: {
    flex: 1,
    alignItems: 'center'
  },
  text: {
    fontSize: 30
  }
});

AppRegistry.registerComponent('weather', () => Weather);
xcode react-native xcode7
4个回答
25
投票

好的,感谢上面@while1的回答,我找到了对我有用的答案。

我上面问题中的代码很好。我必须更改

info.plist
文件。

哇,苹果真是太痛苦了,为什么他们会把事情搞得这么复杂?

我基本上将以下内容添加到

info.plist
文件中。

<key>NSAllowsArbitraryLoads</key>
<true/> 

像这样:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
        <key>NSExceptionDomains</key>
        <dict>
            <key>localhost</key>
            <dict>
                <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                <true/>
            </dict>
        </dict>
    </dict>

请在上面 @while1 的答案中的链接中查看更多信息。


12
投票

您需要更改 info.plist 中的 NSAppTransportSecurity 策略。默认情况下,iOS 8 及更高版本的明文请求被阻止。请参阅传输安全已阻止明文 HTTP


1
投票

你的代码对我来说看起来很熟悉,似乎你正在学习使用 Stephen Grider 提供的 React Native 课程构建应用程序。

即使我也有这个问题。

在 api.js 文件的开头包含

delete GLOBAL.XMLHttpRequest;

像这样:

delete GLOBAL.XMLHttpRequest;
var _ = require('lodash');
var rootUrl = 'http://api.openweathermap.org/data/2.5/weather?APPID=xxxxxxxxxxxxxxxxxxxxxx';

0
投票

在我的例子中,我使用的是真实设备特定(IOS),并且本地后端正在运行,只需更改应用程序中端点的 URL 以使用带有端口的私有本地 IP

在MAC上使用ifconfig获取本地私有IP

会是这样的

en0:标志=8863mtu 1500 选项=6463 以太 c8:89:f3:e5:a0:76 inet6 fe80::146a:e366:7e9c:5d5en0 prefixlen 64 安全范围 ID 0xf inet 192.168.3.50 网络掩码 0xffffff00 广播 192.168.3.255 nd6 选项=201 媒体:自动选择 状态:活跃

在我的例子中是 192.168.3.50,我在端口 4000 中运行带有 graphql 的后端

因此应用程序中的 URL 将是

http://192.168.3.50:4000/graphql

就是这样,不需要任何权限,我只在 IOS 上进行了测试,所以我不知道相同的解决方案是否适用于 Android

import {GraphQLClient} from 'graphql-request';
import {Platform} from 'react-native';

export const client = new GraphQLClient(
  Platform.OS === 'ios'
    ? 'http://192.168.3.50:4000/graphql' // I have before localhost:4000/graphql
    : 'http://10.0.2.2:4000/graphql',
  {
    credentials: 'include',
    mode: 'cors',
  },
);
© www.soinside.com 2019 - 2024. All rights reserved.