Skip to content

Latest commit

 

History

History
229 lines (184 loc) · 10.2 KB

iOS.md

File metadata and controls

229 lines (184 loc) · 10.2 KB

Xamarin Project with Naver Map iOS Framework

SDK API 문서 및 다운 로드

2017.3.30 : v2.1.3 버전으로 변경
iOS용 최신버전SDK(v2.1.3)의 경우 Native Binding을 통하여 App 을 생성할 경우 런타임시 dll 로딩이 안되는 형상이 발생하여
부득이하게 v2.1.1 버전으로 작성함.(혹시 이부분 해결하신분 계시면 내용 공유 부탁드립니다.
)

프로젝트 구성

  • Library : Xamarin.iOS Binding Library 용 NMapViewerSDK.framework Convert 프로젝트
  • App : Xamarin iOS 용 네이버 지도 Sample

Native Binding 프로젝트

  1. sharpie 를 이용하여 ApiDefinitions.cs 및 StructsAndEnums.cs 파일 생성하기 (on MacOS) (sharpie 사용법은 링크를 클릭해보시기 바랍니다. 여러 옵션이 있으나 NMapViewerSDK.framework 변환시 가장 무난하게 변경된 옵션만 표시하도록 하겠습니다.)
sharpie bind -output TempBinding -namespace NMapViewerSDK -framework NMapViewerSDK.framework -sdk iphoneos10.2 -scope NMapViewerSDK.framework/Versions/A/Headers NMapViewerSDK.framework/Versions/A/Headers/*.h -c 
  • (sharpie 를 실행하면 다음과 같은 화면이 보이더라도 당황화지 마세요!!)

    • ApiDefinitions.cs , StructsAndEnums.cs 파일이 생성확인

    • Binding Analysis 내용 확인 <- 코드 수정에 대한 가이드

sharpie result

  1. Native Binding 프로젝트 생성
  • New Solution -> iOS 라이브러리 -> 바인딩 라이브러리 생성
  1. 네이티브 참조 -> 오른쪽 마우스 클릭 -> NMapViewerSDK.framework, ApiGatewayMac.framework 참조

xamarin ios framework

  1. sharpie 로 생성하 ApiDefinitions.cs , StructsAndEnums.cs 파일 내용 복사 또는 Drag and Drop로 프로젝트에 파일 추가
  • sharpie로 생성된 파일은 최종 결과 파일이 아니고, Binging objective-c libraries 등을 참조하여 내용에 맞게 수정해 주어야 함
  1. NMapViewerSDK.framework.linkwith.cs(파일명은 상관없음) 파일 추가.
    참조 : Binging objective-c libraries , ObjCRuntime.LinkWithAttribute Class
using ObjCRuntime;

[assembly: LinkWith("NMapViewerSDK.framework",
                  Frameworks = "ApiGatewayMac",
                  ForceLoad = true,
                  LinkerFlags = "-ObjC -lxml2")]

[assembly: LinkWith("ApiGatewayMac.framework",
                  SmartLink = true,
                  ForceLoad = true,
                  LinkerFlags = "-ObjC -lxml2")]
  1. 경우에 따라 추가코드 생성 (예 : Extension.cs)
  2. iOS 용 App 프로젝트 생성 -> Native Binding 프로젝트 참조
  • 네이버 API 신청시 등록된 iOS Bundle ID 와 Client ID 를 동일하게 설정해 주어야 지도 서비스가 제대로 동작합니다.

info.plist -> Bundle ID

번들아이디 등록

코드 예제
 AppSetting.cs 파일에 Client_ID 수정
 public class AppSetting
  {
       public const string CLIENT_ID = "YOUR_CLIENT_ID"; <- Naver API에서 신청후 생성된 Client ID 를 변경해 줌!
   }

 using NMapViewerSDK.iOS;
...
          mapView = new NMapView(View.Frame)
          {
              //set the delegate for map view
              WeakDelegate = this
          };
          // set the application api key for Open MapViewer Library
          mapView.SetClientId(AppSetting.CLIENT_ID);
          mapView.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
          View.InsertSubview(mapView, 0);

          // set min and max level for range in the UIStepper
          InitStepper(mapView.MaxZoomLevel(), mapView.MinZoomLevel(), 11);
          View.BringSubviewToFront(levelSetpper);

          mapView.SetBuiltInAppControl(true);
          mapView.Layer.AddAnimation(new Animation(this), "mapViewAnimation");

Screenshot

스크린샷1 스크린샷2 스크린샷3 스크린샷4 스크린샷5

  • 말풍선의 경우 화면 좌측으로 붙어서 표시되는 Bug 가 있음(해결하신분 공유부탁드려요~~)

오류

  • MapView 내의 CGRect 객체를 반환하는 값들에 대해 동일한 오류 증상이 보임(변환과정의 오류인지 , Mono 상의 오류인지 잘 모르겠네요. 이부분도 해결해 하신분 공유 Please)
  • unmanaged struct 를 반환하는 Property 및 Method 의 경우 위와 같은 오류가 발생할 수 있음.
        - 자동으로 generated 된 Messaging.cs 파일에서 호출하는 함수외에 별도의 추가 Messagins.cs 파일을 만들어 줌
         - 참조 : 네이티브 라이브러리와의 상호 운영성:모노
자동 gendrated Messaging.cs 파일 위치 -> [native bindng 프로젝트폴더]/obj/ios/ObjCRuntime/Messaging.cs

예 :
CGRect 를 반환하는 Method 를 호출하는 경우 다음과 같은 Method를 호출하게 됨.
이때 CGRect 객체가 struct 타입이기 때문에 위 그림과 같은 오류가 발생

[DllImport(LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")]
public extern static CGRect CGRect_objc_msgSend(IntPtr receiver, IntPtr selector);

수정하기
1. Messaging.cs 파일 프로젝트에 추가

namespace NMapViewerSDK.iOS
{
    internal static class Messaging
    {
        const string LIBOBJC_DYLIB = "/usr/lib/libobjc.dylib";

        ....

                  [DllImport(LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")]
Attribute 추가 ->  [return:MarshalAs(UnmanagedType.Struct)]
                  public extern static CGRect CGRect_objc_msgSend(IntPtr receiver, IntPtr selector);

        ....
    }
}

2. Extensions.cs 파일 추가

    public partial class NMapViewQuartz
    {
        public virtual CGRect ViewFrame
        {
            [Export("viewFrame")]
            get
            {
                CGRect ret;
                if (IsDirectBinding)
                {
                    if (Runtime.Arch == Arch.DEVICE)
                    {
                        if (IntPtr.Size == 8)
                        {
                            ret = global::NMapViewerSDK.iOS.Messaging.CGRect_objc_msgSend(this.Handle, Selector.GetHandle("viewFrame"));  <- 위 Messaging.cs 파일에 추가하 Method 를 호출
                        }
                        else
                        {
                            global::NMapViewerSDK.iOS.Messaging.CGRect_objc_msgSend_stret(out ret, this.Handle, Selector.GetHandle("viewFrame"));
                        }
                    }
                    else if (IntPtr.Size == 8)
                    {
                        global::NMapViewerSDK.iOS.Messaging.CGRect_objc_msgSend_stret(out ret, this.Handle, Selector.GetHandle("viewFrame"));
                    }
                    else
                    {
                        global::NMapViewerSDK.iOS.Messaging.CGRect_objc_msgSend_stret(out ret, this.Handle, Selector.GetHandle("viewFrame"));
                    }
                }
                else
                {
                    if (Runtime.Arch == Arch.DEVICE)
                    {
                        if (IntPtr.Size == 8)
                        {
                            ret = global::NMapViewerSDK.iOS.Messaging.CGRect_objc_msgSendSuper(this.SuperHandle, Selector.GetHandle("viewFrame"));
                        }
                        else
                        {
                            global::NMapViewerSDK.iOS.Messaging.CGRect_objc_msgSendSuper_stret(out ret, this.SuperHandle, Selector.GetHandle("viewFrame"));
                        }
                    }
                    else if (IntPtr.Size == 8)
                    {
                        global::NMapViewerSDK.iOS.Messaging.CGRect_objc_msgSendSuper_stret(out ret, this.SuperHandle, Selector.GetHandle("viewFrame"));
                    }
                    else
                    {
                        global::NMapViewerSDK.iOS.Messaging.CGRect_objc_msgSendSuper_stret(out ret, this.SuperHandle, Selector.GetHandle("viewFrame"));
                    }
                }
                return ret;
            }

        }

        ....
    }

3. ApiDefinitions.cs 에 정의되어 있는 ViewFrame Property 를 주석 처리

    [BaseType(typeof(UIView))]
    interface NMapViewQuartz
    {
      ....
      
        //[Export("viewFrame")]
        //CGRect ViewFrame { get; }

      ....
    }

struct반환

  • 제대로된 값을 반환함

Reference