환경
OS : macOS High Sierra 10.13.3
Xcode : 9.2(9C40b)
0. Project 생성
iOS App - Ojbective-C로 선택
1. CoreLocation Framework 추가
[Build Phases] - [Link Binary With Libraries]에 CoreLocation.framework를 추가
2. 위치기반허용
기기의 위치정보는 개인정보이기 때문에 반드시 필요하다.
3. Source code
ViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
@interface ViewController : UIViewController <CLLocationManagerDelegate>{
IBOutlet UITextView *loclogview;
IBOutlet UITextField *corelocation_address;
}
@end
ViewController.m
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic , strong) CLLocationManager *locationManager;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.locationManager = [[CLLocationManager alloc]init];
self.locationManager.delegate = self;
// 사용중에만 위치 정보 요청
if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])
{
[self.locationManager requestWhenInUseAuthorization];
}
// // 항상 위치 정보 사용 요청
// if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
// {
// [self.locationManager requestAlwaysAuthorization];
// }
corelocation_address.text = @"";
}
-(void)logAddView:(NSString *)log{
NSDate *localDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
NSDateFormatter *timeFormatter = [[NSDateFormatter alloc]init];
localDate = [NSDate date];
dateFormatter.dateFormat = @"MM/dd/yy";
timeFormatter.dateFormat = @"HH:mm:ss";
NSString *tmr = [NSString stringWithFormat:@"[%@__%@]",
[dateFormatter stringFromDate:localDate],[timeFormatter stringFromDate:localDate]];
[loclogview insertText:[NSString stringWithFormat:@"%@ : %@\n",tmr,log]];
}
-(IBAction)btn_CoreLocation_Address:(id)sender{
CLGeocoder* geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:corelocation_address.text
completionHandler:^(NSArray *placemarks, NSError *error)
{
// NSLog(@"%@",[placemarks description]);
NSLog(@"plcaemarks count = %lu",(unsigned long)[placemarks count]);
if ([placemarks count] == 0) //검색결과가 아무것도 없을 때
{
NSLog(@"result = nil");
//경고창
[self logAddView:@"[btn_CoreLocation_Address] 주소의 검색결과를 찾을수 없습니다. 위도 : 0.0 // 경도 : 0.0"];
return ;
}
else
{
CLPlacemark* p = [placemarks objectAtIndex:0]; //첫번째 검색결과 사용
CLCircularRegion* region = (CLCircularRegion *)p.region;
// region.center.latitude
// region.center.longitude
[self logAddView:[NSString stringWithFormat:@"[btn_CoreLocation_Address] 주소 : %@ 위도 : %f // 경도 : %f" ,
corelocation_address.text,region.center.latitude,region.center.longitude ]];
}
}];
}
-(IBAction)btn_CoreLocation_nowLocation:(id)sender{
if(self.locationManager == nil)
{
self.locationManager = [[CLLocationManager alloc]init];
self.locationManager.delegate = self;
}
[self.locationManager startUpdatingLocation];
// if([CLLocationManager locationServicesEnabled])
// {
// [self.locationManager stopUpdatingLocation];
// }
// else
// {
// [self.locationManager startUpdatingLocation];
// }
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
[self logAddView:[locations lastObject]];
}
-(IBAction)clearLogView:(id)sender{
loclogview.text = @"";
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
3. 테스트
기본적으로 테스트만 빠르게 진행하기 위해 급하게 작성
오차범위 테스트 , 구글 , 다음 API 테스트는 추후진행
기기의 LTE 모드 , Wi-Fi모드 .. 센서 등등 환경에 따라 굉장히 예민하게 작용되는 부분이기 때문에 추가적으로 공부가 필요한듯하다.
Goole Places API 홈페이지 접속
https://developers.google.com/places/ios-api/?hl=ko
프로젝트 이름을 생성하고 키를 생성해준다(키값은 따로 저장)
아래 주소에 아주아주 친절하게 써있다 그래도 따라해본다.
https://developers.google.com/places/ios-api/start?hl=ko
현재 위치정보는 다음 주소를 통해서 확인해보았다.
https://developers.google.com/places/ios-api/current-place?hl=ko
6. Source code
ViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <GooglePlaces/GooglePlaces.h>
@interface ViewController : UIViewController <CLLocationManagerDelegate >{
IBOutlet UITextView *loclogview;
IBOutlet UITextField *corelocation_address;
GMSPlacesClient *_placesClient;
}
@end
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_placesClient = [GMSPlacesClient sharedClient];
}
-(IBAction)btn_GoogleLocation_nowLocation:(id)sender{
[_placesClient currentPlaceWithCallback:^(GMSPlaceLikelihoodList *placeLikelihoodList, NSError *error){
if (error != nil) {
NSLog(@"Pick Place error %@", [error localizedDescription]);
return;
}
if (placeLikelihoodList != nil) {
GMSPlace *place = [[[placeLikelihoodList likelihoods] firstObject] place];
if (place != nil) {
/*
## GMSPlace Class ##
name – 장소의 이름.
placeID – 장소의 텍스트 식별자. 이 페이지의 나머지 부분에서 장소 ID에 대해 더 자세히 알아보세요.
coordinate – 장소의 지리적 위치로, 위도와 경도 좌표로 지정됩니다.
openNowStatus – 장소 정보를 요청했을 때 장소가 열리는지 여부를 나타냅니다.
phoneNumber – 국제 형식의 장소 전화번호.
formattedAddress – 사람이 읽을 수 있는 형식의 장소 주소.
rating – 장소의 합산 평점으로, 합산 사용자 리뷰에 근거하여 1.0 ~ 5.0 범위의 값을 가진 소수로 반환됩니다.
priceLevel – 이 장소의 가격 레벨로, 0(가장 쌈) ~ 4(가장 비쌈) 범위의 값을 가진 정수로 반환됩니다.
types – 이 장소를 특징짓는 장소 유형 목록. 지원 유형 문서를 참조하세요.
website – 장소의 웹사이트 URI(알려진 경우). 장소와 연관된 사업체나 기타 주체가 관리하는 웹사이트입니다.
attributions – 앱이Google Places API for iOS에서 검색한 장소 세부정보를 사용할 경우, 사용자에게 표시해야 하는 특성이 포함된 NSAttributedString. 특성 검색 및 표시에 대한 자세한 내용은 특성 가이드를 참조하세요.
addressComponents – 장소의 주소 구성 요소를 나타내는 GMSAddressComponent 객체의 배열입니다. 이러한 구성 요소는 장소의 주소에 대한 구조화된 정보를 추출하기 위한 목적(예: 장소가 위치한 도시 찾기)으로 제공됩니다. 주소 형식에 이 구성 요소를 사용하지 마십시오. 대신 현지화된 기본 제공 주소를 제공하는 formattedAddress 속성을 사용하십시오.
*/
[self logAddView:[NSString stringWithFormat:@"google places API location : %f . %f (%@,%@)" , place.coordinate.latitude , place.coordinate.longitude ,place.name ,[[place.formattedAddress componentsSeparatedByString:@", "] componentsJoinedByString:@"\n"] ]];
}
}
}];
}
6. Project File
Corelocation + Google place API 적용버전
단순 테스트용
google framework 용량이 100메가 넘어서 Framework 별도로 넣고 테스트해야함
DaumMap API 제공 Url
iOS SDK 1.3.0을 다운로드하였다.(역시다...Framework)
자세한 가이드는 아래 주소에 친절하게 설명되어 있다. bundle id 등록 Key 생성.. Google과 거의 비슷한 방법이다.
http://apis.map.daum.net/ios/guide/
아래 에러가 발생하면 다음과 같이 수정한다.
[Build Settings] - [Enable Bitcode] -> No 변경할것
설명대로 적용하면 delegate가 정상적으로 동작하지 않는데 MTMap...이 아니라 mapView로 바뀌었고 델리게이트가 정상적으로 잘 동작하지 않았다.
- (void)MTMapView:(MTMapView *)mapView centerPointMovedTo:(MTMapPoint *)mapCenterPoint {
// [self.eventResultLabel setText:[NSString stringWithFormat:@"Camera Position: lat:%f, lng: %f", mapCenterPoint.mapPointGeo.latitude, mapCenterPoint.mapPointGeo.longitude]];
NSLog(@"%@",[NSString stringWithFormat:@"Camera Position: lat:%f, lng: %f", mapCenterPoint.mapPointGeo.latitude, mapCenterPoint.mapPointGeo.longitude]);
}
-(void)viewDidAppear:(BOOL)animated{
MTMapPOIItem* poiItem1 = [MTMapPOIItem poiItem];
poiItem1.itemName = @"City on a Hill";
poiItem1.mapPoint = [MTMapPoint mapPointWithGeoCoord:MTMapPointGeoMake(37.541889,127.005470)];
poiItem1.markerType = MTMapPOIItemMarkerTypeBluePin;
poiItem1.showAnimationType = MTMapPOIItemShowAnimationTypeDropFromHeaven;
poiItem1.draggable = YES;
poiItem1.tag = 153;
[mapView addPOIItems:[NSArray arrayWithObjects:poiItem1,nil]];
[mapView fitMapViewAreaToShowAllPOIItems];
MTMapCircle *circle = [MTMapCircle circle];
circle.circleCenterPoint = [MTMapPoint mapPointWithGeoCoord:MTMapPointGeoMake(37.541889, 127.005470)];
circle.circleLineColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.5];
circle.circleFillColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.5];
circle.circleRadius = 300;
[mapView addCircle:circle];
[mapView fitMapViewAreaToShowCircle:circle];
[mapView currentLocationTrackingMode];
[mapView setCurrentLocationTrackingMode:MTMapCurrentLocationTrackingOnWithHeading];
}
일단 위치정보를 가져오는 중요한 이유는 바로 현재 위치 또는 원하는 곳의 지역정보를 확인하기 위함인데 Google , 카카오 , Corelocation 세가지를 테스트해본 결과
Google은 자체적으로 위도 경도를 구하는 메서드가 있는것 같은데 카카오는 CoreLocation으로 현재 위치를 가져오는 것 같았다.
근데 Google Place API를 적용할때도 Corelocation.Framework가 기본적으로 추가하라고 나오는것 보니... 구글도 Corelocation으로 정보를 가져오는 것 같기도 하다(추측)
2018-03-08 15:35:27.965508+0900 MyLocation[2260:2425251] Info: core location updates new location ... <+37.57526932,+126.88835749> +/- 65.00m (speed -1.00 mps / course -1.00) @ 2018. 3. 8. 오후 3시 35분 27초 대한민국 표준시
카카오 API로 실시간 지도를 확인할때 로그에 다음과 같이 Corelocation log가 남았다.
지도 표기는 카카오가 정확한것 같아 한개의 프로젝트에 카카오(지도) + Corelocation(위도경도정보) + Google(비교자료용)으로
테스트 app으로 작업을 해보자
9. SourceCode
ViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <GooglePlaces/GooglePlaces.h>
#import <DaumMap/MTMapView.h>
#import <DaumMap/MTMapGeometry.h>
#import <DaumMap/MTMapPOIItem.h>
#import <DaumMap/MTMapPolyline.h>
#import <DaumMap/MTMapView.h>
#import <DaumMap/MTMapCameraUpdate.h>
#import <DaumMap/MTMapReverseGeoCoder.h>
@interface ViewController : UIViewController <CLLocationManagerDelegate , MTMapViewDelegate , MTMapReverseGeoCoderDelegate>{
IBOutlet UITextView *loclogview;
IBOutlet UITextField *corelocation_address;
GMSPlacesClient *_placesClient;
MTMapView *mapView;
}
@end
ViewController.m
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic , strong) CLLocationManager *locationManager;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.locationManager = [[CLLocationManager alloc]init];
self.locationManager.delegate = self;
// 사용중에만 위치 정보 요청
if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])
{
[self.locationManager requestWhenInUseAuthorization];
}
// // 항상 위치 정보 사용 요청
// if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
// {
// [self.locationManager requestAlwaysAuthorization];
// }
_placesClient = [GMSPlacesClient sharedClient];
corelocation_address.text = @"";
// Daum
mapView = [[MTMapView alloc]init];
mapView = [[MTMapView alloc] initWithFrame:CGRectMake(10, 84, 300, 300)];
mapView.delegate = self;
mapView.baseMapType = MTMapTypeStandard;
[self.view addSubview:mapView];
}
-(void)viewDidAppear:(BOOL)animated{
[mapView currentLocationTrackingMode];
[mapView setCurrentLocationTrackingMode:MTMapCurrentLocationTrackingOnWithHeading];
}
- (void)viewWillDisappear:(BOOL)animated {
if (mapView != nil) {
mapView = nil;
}
}
-(IBAction)btn_CoreLocation_Address:(id)sender{
if([corelocation_address.text isEqualToString:@""])
{
[loclogview insertText:@"주소를 입력해주세요\n"];
}
else
{
CLGeocoder* geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:corelocation_address.text
completionHandler:^(NSArray *placemarks, NSError *error)
{
// NSLog(@"%@",[placemarks description]);
NSLog(@"plcaemarks count = %lu",(unsigned long)[placemarks count]);
if ([placemarks count] == 0) //검색결과가 아무것도 없을 때
{
NSLog(@"result = nil");
//경고창
[self logAddView:@"[btn_CoreLocation_Address] 주소의 검색결과를 찾을수 없습니다. 위도 : 0.0 // 경도 : 0.0"];
return ;
}
else
{
CLPlacemark* p = [placemarks objectAtIndex:0]; //첫번째 검색결과 사용
CLCircularRegion* region = (CLCircularRegion *)p.region;
// region.center.latitude
// region.center.longitude
[self logAddView:[NSString stringWithFormat:@"[btn_CoreLocation_Address] 주소 : %@ 위도 : %f // 경도 : %f" ,
corelocation_address.text,region.center.latitude,region.center.longitude ]];
}
}];
}
}
-(IBAction)btn_CoreLocation_nowLocationStart:(id)sender{
[self.locationManager startUpdatingLocation];
[self logAddView:@"iOS Corelocation location start"];
}
-(IBAction)btn_CoreLocation_nowLocationStop:(id)sender{
[self.locationManager stopUpdatingLocation];
[self logAddView:@"iOS Corelocation location stop"];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
if([locations count] != 0)
{
for(int i=0 ; i < [locations count] ; i++)
{
// CLLocation *currentLocation = [locations lastObject];
CLLocation *currentLocation = [locations objectAtIndex:i];
[self logAddView:[NSString stringWithFormat:@"iOS Corelocation location : %f , %f" , currentLocation.coordinate.latitude , currentLocation.coordinate.longitude]];
}
}
// CLGeocoder *geocoder = [[CLGeocoder alloc]init];
// [geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// if(!error)
// {
// CLPlacemark *placemark = [placemarks lastObject];
// NSString *placemarkAt = [NSString stringWithFormat:@"\ncountry : %@\nthoroughfare : %@\nsubThoroughfare : %@\npostalCode : %@\npostalAddress : %@\npostalCode : %@\nlocality : %@\nadministrativearea : %@",
// placemark.country,
// placemark.thoroughfare,
// placemark.subThoroughfare,
// placemark.postalCode,
// placemark.postalAddress,
// placemark.postalCode,
// placemark.locality,
// placemark.administrativeArea
// ];
//
// [self logAddView:[NSString stringWithFormat:@"iOS Corelocation location : %f , %f" , currentLocation.coordinate.latitude , currentLocation.coordinate.longitude]];
// [self logAddView:[NSString stringWithFormat:@"%@",placemarkAt]];
//
//
// }
// }];
}
-(IBAction)btn_GoogleLocation_nowLocation:(id)sender{
[self logAddView:@"지금은 사용할 수 없습니다.(Google places api)"];
return;
[_placesClient currentPlaceWithCallback:^(GMSPlaceLikelihoodList *placeLikelihoodList, NSError *error){
if (error != nil) {
NSLog(@"Pick Place error %@", [error localizedDescription]);
return;
}
if (placeLikelihoodList != nil) {
GMSPlace *place = [[[placeLikelihoodList likelihoods] firstObject] place];
if (place != nil) {
/*
## GMSPlace Class ##
name – 장소의 이름.
placeID – 장소의 텍스트 식별자. 이 페이지의 나머지 부분에서 장소 ID에 대해 더 자세히 알아보세요.
coordinate – 장소의 지리적 위치로, 위도와 경도 좌표로 지정됩니다.
openNowStatus – 장소 정보를 요청했을 때 장소가 열리는지 여부를 나타냅니다.
phoneNumber – 국제 형식의 장소 전화번호.
formattedAddress – 사람이 읽을 수 있는 형식의 장소 주소.
rating – 장소의 합산 평점으로, 합산 사용자 리뷰에 근거하여 1.0 ~ 5.0 범위의 값을 가진 소수로 반환됩니다.
priceLevel – 이 장소의 가격 레벨로, 0(가장 쌈) ~ 4(가장 비쌈) 범위의 값을 가진 정수로 반환됩니다.
types – 이 장소를 특징짓는 장소 유형 목록. 지원 유형 문서를 참조하세요.
website – 장소의 웹사이트 URI(알려진 경우). 장소와 연관된 사업체나 기타 주체가 관리하는 웹사이트입니다.
attributions – 앱이Google Places API for iOS에서 검색한 장소 세부정보를 사용할 경우, 사용자에게 표시해야 하는 특성이 포함된 NSAttributedString. 특성 검색 및 표시에 대한 자세한 내용은 특성 가이드를 참조하세요.
addressComponents – 장소의 주소 구성 요소를 나타내는 GMSAddressComponent 객체의 배열입니다. 이러한 구성 요소는 장소의 주소에 대한 구조화된 정보를 추출하기 위한 목적(예: 장소가 위치한 도시 찾기)으로 제공됩니다. 주소 형식에 이 구성 요소를 사용하지 마십시오. 대신 현지화된 기본 제공 주소를 제공하는 formattedAddress 속성을 사용하십시오.
*/
[self logAddView:[NSString stringWithFormat:@"google places API location : %f . %f (%@,%@)" , place.coordinate.latitude , place.coordinate.longitude ,place.name ,[[place.formattedAddress componentsSeparatedByString:@", "] componentsJoinedByString:@"\n"] ]];
}
}
}];
}
-(IBAction)clearLogView:(id)sender{
loclogview.text = @"";
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)logAddView:(NSString *)log{
NSDate *localDate;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
NSDateFormatter *timeFormatter = [[NSDateFormatter alloc]init];
localDate = [NSDate date];
dateFormatter.dateFormat = @"MM/dd/yy";
timeFormatter.dateFormat = @"HH:mm:ss";
NSString *tmr = [NSString stringWithFormat:@"[%@__%@]",
[dateFormatter stringFromDate:localDate],[timeFormatter stringFromDate:localDate]];
[loclogview insertText:[NSString stringWithFormat:@"%@ : %@\n",tmr,log]];
}
@end
'Apple > Objective - C' 카테고리의 다른 글
[Objective C] base64EncodedStringWithOptions (0) | 2018.09.27 |
---|---|
[iOS] NetworkExtension (0) | 2018.03.07 |