MapTest 프로젝트 api 호출 테스트중 Network request failed 에러가 나면서 해당 API가 호출되지않는 현상이 발생하였다.



Xcode 열어서 info.plist 파일을 위와 같이 수정하고 다시 테스트 해보았다. 해당옵션 추가시 정상적으로 호출되었다. 

혹시 나 동일현상이 일어나는경우를 대비해서 해당 내용을 기록함 


Network request failed 관련 참고 URL


https://stackoverflow.com/questions/30720813/cfnetwork-sslhandshake-failed-ios-9?fbclid=IwAR0-0G1dVomWFV091WZz6XYqkY7h1TfVwduWk1NED915GTjF-AhGk54GYdk

https://www.facebook.com/groups/reactapp/search/?query=Network%20request%20failed&epa=SEARCH_BOX

https://www.youtube.com/watch?v=iZpI-jqvs18

https://www.youtube.com/watch?v=shstJgkLW-I

https://github.com/facebook/react-native/issues/16081

https://stackoverflow.com/questions/38418998/react-native-fetch-network-request-failed

https://stackoverflow.com/questions/30720813/cfnetwork-sslhandshake-failed-ios-9?fbclid=IwAR0-0G1dVomWFV091WZz6XYqkY7h1TfVwduWk1NED915GTjF-AhGk54GYdk

iOS 9 / OS X 10.11 앱 네트워크 보안 정책


블로그 이미지

클라인STR

,



연관포스팅 링크 바로가기


iOS Simulator 실행한다. 




Simulator -> Debug -> Location -> Custom Location 선택한다.



위도와 경도에 값을 원하는 값으로 설정하고 OK 버튼을 선택한다음 다시 테스트 코드를 실행한다. 



설정한 Location 으로 값이 변경된걸 확인할 수 있다. 




원하는 장소에 위도와 경도를 가장 쉽게아는 방법은 구글지도를 이용하는 것이다. 


구글지도를 접속한다.



지도검색란에 주소를 입력한다.




지도 위치꼭지란을 클릭하고 이곳이 궁금한가요? 클릭한다. 




웹브라우저 하단에 위도, 경도가 숫자로 표시된다. 


참고 

https://stackoverflow.com/questions/42377279/react-native-i-cant-find-my-current-locationgeolocation-ios

https://stackoverflow.com/questions/52430007/xcode-10-ios-12-simulator-location-simulation-fails-on-city-bicycle-ride-city

블로그 이미지

클라인STR

,

IOS인 경우 react-native init 통해서 프로젝트를 생성한경우 info.plist에 필요한 키가 설정되어있다. (NSLocationWhenInUseUsageDescription)


geolocation api는 navigator.geolocation 통해 액세스 한다.



geolocation.getCurrentPosition(geo_success, [geo_error], [geo_options]);


getCurrentPostion 함수는 파라메터로 성공콜백, 실패콜백, Option Object 세가지 매개변수를 허용한다.

성공콜백은 아래와 같은 object 객체를 전달한다. 


1
2
3
4
5
6
7
8
9
10
11
12
{
  "timestamp"1484669056399.49,
  "coords": {
    "accuracy"5,
    "altitude"0,
    "altitudeAccuracy"-1,
    "heading"-1,
    "latitude"37.785834,
    "longitude"-122.406417,
    "speed"-1
  }
}
cs


오류콜백은 에러메시지를 전달한다. Option Object는 enableHighAccuracy (boolean), timeout (milliseconds), maximumAge (milliseconds) 구성되어있다.


timeout : api 요청시 timeout 값 설정한다. (응답반응할수 있는 최대 허용시간 Default INFINITY)

enableHighAccuracy : GPS를 사용할지 여부를 나타낸다. 

maximumAge : 반환된 값의 최대 보존기간을 설정한다.  (Default INFINITY) 0으로 설정하면 장치가 캐시된 위치를 사용할 수 없다. Default 값을 INFINITY 설정하면 항상 캐싱된 값을 반환한다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
export default class App extends Component {
  
  constructor(props) {
    super(props);
    this.state = {
      latitude: null,
      longitude: null,
      error: null,
    };
  }
  componentDidMount() {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        this.setState({
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
          error: null,
        });
      },
      (error) => this.setState({ error: error.message }),
      { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 },
    );
  }
  render() {
    return (
      <View style={{ flexGrow: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Latitude: {this.state.latitude}</Text>
        <Text>Longitude: {this.state.longitude}</Text>
        {this.state.error ? <Text>Error: {this.state.error}</Text> : null}
      </View>
    );
  }
}
 
cs




latitude : 위도이고 , longitude 경도를 나타낸다.


출처  

https://facebook.github.io/react-native/docs/geolocation#getcurrentposition

https://hackernoon.com/react-native-basics-geolocation-adf3c0d10112

https://medium.com/@icodeinswift/location-permissions-in-ios-apps-always-or-when-in-use-371c1b22e02e

https://medium.com/@icodeinswift/location-permissions-in-ios-apps-always-or-when-in-use-371c1b22e02e


블로그 이미지

클라인STR

,

테스트용 프로젝트를 생성한다.

react-native init MapTest --version="0.56.0"

cd MapTest



npm install --save react-native-maps




react-native link react-native-maps





cocoa pods 설치하기


sudo gem install cocoapods



MapTest 폴더내에서 cd ios 명령어로 ios 폴더러 접근한뒤 pod init 명령어를 실행한후 open podfile 명령을 실행한다.



podfile 빨간선으로 체크한 부분을 수정해줘야한다. 




pod install 명령을 실행한다. 


Xcode를 실행하여 .xcworkspace 파일을 open 한다. 



Project 에 AirGoogleMaps을 추가한다.





AirGoogleMaps을 드래그하여 프로젝트 폴더 내부로 옮기면 아래와같은 화면이 출력된다. 


Added folders에서 Create groups 선택하고 Finish 버튼을 선택한다. 










Libraries folder 선택후 Add Files ... 를 선택하여 AirMaps.xcodeproj 추가한다. 







Build Phase -> Link Binary With Libraries -> libAirMaps.a 추가한다. 




Build Setting -> Header Search Paths 선택하고 위에 스샷과같이 $(SRCROOT)/../node_models/react-native-maps/AirMaps 선택한다.




AppDelegate.m 파일을 선택하고 빨간영역에 내용을 추가한다. 18라인에 @"API서비스키" 입력한다.



Xcode에서  Product->Clean,  Product->Build 선택한다. 

Build가 실패했다고 나오는데, 에러표시를 클릭하면 아래와 같은 에러가 난다.






네비게이터에서 All 을선택하고 Preprocessor Macros -> HAVE_GOOGLE_MAPS=1 값을 선택하고,  Product->Clean,  Product->Build 다시 한다. 빌드가 성공하면 App.js를 아래와 같이 작성한다. 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import MapView, {PROVIDER_GOOGLE} from 'react-native-maps';
 
export default class App extends Component {
  render() {
    return (
      <MapView
        provider={PROVIDER_GOOGLE}
        style={{flex:1}}
        region={{
          latitude: 42.882000,
          longitude: 74.582748,
          latitudeDelta: 0.0922,
          longitudeDelta: 0.0421
        }}
        showsUserLocation
        />
    );
  }
}

cs



프로젝트를 실행한다. 






react-native-maps 정상적으로 호출되는것을 확인하였다. 

react-native-maps 설정하고 테스트하는데 생각보다 오래걸렸다. ㅠㅠ




참고

https://github.com/react-native-community/react-native-maps 

https://github.com/react-native-community/react-native-maps/blob/master/docs/installation.md

https://medium.com/quick-code/react-native-location-tracking-14ab2c9e2db8

https://medium.freecodecamp.org/how-to-integrate-maps-in-react-native-using-react-native-maps-5745490fe055

https://medium.com/@juanli_dev/install-react-native-maps-bccae45b6083

https://medium.com/@mehulmistri/integrate-airbnb-google-maps-in-a-react-native-app-889f0c31a7a8

https://github.com/react-native-community/react-native-maps/issues/2573

블로그 이미지

클라인STR

,

FlatList에서 무한 스크롤은 onEndReachedThresholdonEndReached prop을 통해 구현 한다.

스크롤이 onEndReachedThreshold에 설정한 값에 도달하면 onEndReachd 메서드가 실행된다.

onEndReachedThreshold 는 스크롤 목록이 보이는 가장자리 길이 기준으로 목록의 아래쪽 가장자리가 콘텐츠이 끝에서부터 onEndReached 콜백을 트리거한다. 이 값이 0.5인경우 목록이 보이는 길이의 절반내에 있을때 onEndReached 메서드를 실행한다.



1
2
3
4
5
6
<FlatList
              data={this.state.data}
       
              onEndReached={this.handleLoadMore}
              onEndReachedThreshold={0}
            />

cs



1
2
3
4
5
6
7
8
9
10
 handleLoadMore = () => {
        this.setState(
          {
            page: this.state.page + 1
          },
          () => {
            this.makeRemoteRequest();
          }
        );
      };
cs



onEndReachedThreshold 값이 클수록 스크롤영역이 끝에 닿기전에 데이터를 요청하게끔 되어있다.



원문출처

블로그 이미지

클라인STR

,

이전글 보러가기 

 React Native FlatList Component  - #1

 React Native FlatList Component  - #2 




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
this.state = {
            
            refreshing: false
        };
 
 
 this.setState({
                
                refreshing: false
              });
 
 
 .catch(error => {
            this.setState({error, loading: false});
})


cs


state 값에 refreshing 플래그를 추가한다. 데이터를 새로 받아오거나, 오류가난경우 플래그를 false 초기화하는 코드를 추가한다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<FlatList
              data={this.state.data}
              renderItem={({ item }) => (
                <ListItem
                  roundAvatar
                  title={`${item.name.first} ${item.name.last}`}
                  subtitle={item.email}
                  avatar={{ uri: item.picture.thumbnail }}
                  containerStyle={{borderBottomWidth:0}}
                />
              )}
              
              . . . 
              refreshing={this.state.refreshing}
              onRefresh={this.handleRefresh}
            />
cs


refreshing 값을 state refreshing 값으로 설정하고, onRefresh refresh 메서드를 지정하고 아래와 같이 메서드를 구성한다.



1
2
3
4
5
6
7
8
9
10
11
12
 handleRefresh = () => {
        this.setState(
          {
            page: 1,
            seed: this.state.seed + 1,
            refreshing: true
          },
          () => {
            this.makeRemoteRequest();
          }
        );
      };
cs


page 값을 초기화 시키고, refreshing 값을 true로 변환한다. 데이터 조회 함수를 호출한다. 




원문출처

ReactNative Doc FlatList

블로그 이미지

클라인STR

,

스플래쉬(Splash) 화면이란 ? 앱이 구동을 시작할때 켜지기 전 나오는 화면을 말한다.  어플리케이션에서 실행에 필요한 데이터를 불러오는데 이용되며, 브랜드 명칭을 알려주는데도 사용된다. 




1
2
3
4
5
6
7
8
9
10
11
12
13
import Splash from "./src/Splash";
 
 
 
export default class App extends Component {
 
 
  render() {
    return (
      <Splash />
    );
  }
}

cs

[App.js]

Splash.js 파일을 생성하고 render 함수에 return 값으로 호출한다.



1
2
3
4
5
6
7
8
9
10
render() {
    return (
      <View style ={styles.container}>
        <Text style={styles.title}> Hello World !!!! </Text>
        <Text style={styles.subtitle}> Powered by React Native </Text>
      </View>  
      
    );
  }
 
cs

View컴포넌트 내부에 Text 컴포넌트 두개를 배치했을때의 화면구성이다.

1
2
3
4
5
6
7
8
 <View style ={styles.container}>
        <View style={style.titleContainer}>
            <Text style={styles.title}> Hello World !!!! </Text>
        </View>
        <View>
            <Text style={styles.subtitle}> Powered by React Native </Text>
        </View>
      </View>

cs

Text 컴포넌트를 View 컴포넌트로 각각 감싸고 titleContainer영역을 따로 지정한뒤 , backGroundColor 속성을 다르게 지정하여 레이아웃구성을 잡아준다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import React, { Component } from 'react';
import { View, Text , StyleSheet } from 'react-native';
 
export default class Splash extends Component {
  constructor(props) {
    super(props);
    this.state = {
    };
  }
 
  render() {
    return (
      <View style ={styles.container}>
        <View style={styles.titleContainer}>
            <Text style={styles.title}> Hello World !!!! </Text>
        </View>
        <View>
            <Text style={styles.subtitle}> Powered by React Native </Text>
        </View>
      </View>
    );
  }
}
 
 
 
const styles = StyleSheet.create({
    
    container: { 
        // backgroundColor: 'red', 
        backgroundColor : '#3498db',
        flex: 1
        justifyContent: "center"
        alignItems: "center"  
    },
    title : {
        color : 'white',
        fontSize: 35,
        fontWeight: 'bold'
    },
    subtitle : {
        color : 'white',
        fontWeight: '200'
    }, titleContainer : {
        justifyContent : 'center',
        flex : 1
    }
});

cs

[Splash.js]

완성된 Splash 화면인데, 해당화면을 좀 수정해서 Weather App 스플래쉬화면으로 변경할 예정이다. 


백그라운드컬러피커 참고 




블로그 이미지

클라인STR

,

 Image Component 

.
├── button.js
└── img
    ├── check.png
    ├── check@2x.png
    └── check@3x.png

이미지 모듈은 js 모듈이 해석되는것과 같은 방법으로 해석된다. 이미지 파일도 자바스크립트 파일과 마찬가지로 check.ios.png, check.andoid.png 파일이 존재할 때 리액트 네이티브 패키지는 플랫폼에 따라 그에 맞는 이미지를 불러온다.


1
<Image source = {require('./assets/rn-school-logo.png')} />
cs



1
2
3
4
<Image
          source ={{uri : "https://reactjs.org/logo-og.png"}}
          style={{width300height300}}
          />
cs


정적이미지 리소스에 접근할경우  사이즈를 지정해줄 필요가없지만 Network Image 리소스인경우는 반드시 이미자 사이즈를 지정해 줘야한다. 지정하지 않은경우 이미지가 제대로 보이지 않는다.


[원격이미지에 사이즈를 지정한경우]


[이미지 사이즈를 지정하지않은경우]



Image 컴포넌트의 장점


  1.  iOS and Android 운영체제 동일하게 사용가능하다.
  2. 이미지 파일은 js파일과 동일하게 관리되고 사용된다.
  3. 전역이름 공간이 필요없으며, 이름충돌에 대해서 걱정할 필요가없다.
  4. 실제로 사용된 이미지만 앱에 패키징된다.
  5. 이미지를 추가하고 변경하는데 있어서 app을 재기동할 필요없이 시뮬레이터를 reload하면 된다.
  6. 패키져가 이미지 크리를 알고있으므로 코드에 복제할 필요가 없다.
  7. 이미지를 npm 패키지를 통해 패포할수 있다.



// GOOD <Image source={require('./my-icon.png')} />; // BAD var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive'; <Image source={require('./' + icon + '.png')} />; // GOOD var icon = this.props.active ? require('./my-icon-active.png') : require('./my-icon-inactive.png'); <Image source={icon} />;



이미지를 동적으로 사용해야되는경우 style객체를 이용하여 변경한다.  BAD 케이스 처럼 구문을 사용하지 않도록 한다. 



resizeMode

프레임이 원본 이미지 크기와 일치하지 않을때 이미지 크기를 조정하는 방법을 결정한다. 


cover, contain, stretch, repeat, center 속성이 존재한다.


cover : 이미지의 너비와 높이가 뷰의 해당치수와 같거나 커지도록 이미지 비율을 균일하게 조정한다.


contain : 이미지의 너비와 높이가 뷰의 해당치수와 동일하거나 작도록 이미지 비율을 균일하게 조정한다.


stretch : 크기와 높이를 독립적으로 조정하며 src 종횡비가 변경될 수 있다. 


repeat : view에 프레임을 덮기위해 이미지를 반복한다.



원문출처 : https://facebook.github.io/react-native/docs/image



블로그 이미지

클라인STR

,