레이블이 ios인 게시물을 표시합니다. 모든 게시물 표시
레이블이 ios인 게시물을 표시합니다. 모든 게시물 표시

2023년 10월 8일 일요일

KMM IOS COMPOSE ALPHA

KMM IOS COMPOSE ALPHA

iOS용 Compose Alpha가 공식적으로 출시

iOS용 Jetpack Compose Multiplatform이 드디어 공식적으로 알파 지원을 출시했습니다.

https://github.com/JetBrains/compose-multiplatform-ios-android-template/#readme

이제까지는 IOS는 주로 도메인의 미지니스 로직에서만 사용하였는데요.
이제 UI부분에서도 사용할수 있게 되어 갑니다.
compose-jb는 공식적으로 compose-multiplatform으로 이름이 바뀌었고 템플릿 프로젝트는 다양한 플랫폼에 제공되었습니다.

또한, iOS 지원에 이어 compose-multiplatform1.4.0 버전이 출시되었는데 , 즉 iOS를 경험하고 싶은 분들은 1.4 버전에서 사용해 보아야 하며 ,Android Studio Flamingo 새 버전과 마찬가지로 본격적으로 시작될 예정입니다. JDK 17을 지원합니다.

이제 공식적으로 Kotlin을 사용하여 유사한 iOS UI를 작성할 수 있으며 Swift-UI와 유사한 개발 경험을 가질 수 있습니다. (잘가. 복잡한 XML). 기존 Compose 프로젝트를 iOS 애플리케이션으로 보다 쉽게 ​​컴파일하여 UI를 구현할 수도 있습니다.

현재 iOS 지원은 아직 알파 단계로, 베타 단계에 이르지 못한 경우 API 및 호환성에 일부 변화가 있을 수 있으나, 정식 출시된 버전에서는 이미 동일한 Kotlin 코드를 사용하여 컴파일하는 경험을 하실 수 있습니다.

KMM(Kotlin Multiplatform Mobile)은 원래 iOS 플랫폼을 지원하고, Compose Multiplatform은 KMM을 기반으로 구축되었기 때문에 블루투스, 카메라 등 iOS 네이티브 API를 지원하는 데에는 큰 문제가 없을 것이며, 동시에 이제 임베디드[MKMapView 와 같은 기본 UI 보기 도 지원됩니다 .

CocosPods 등이 사용가능한 환경(주로 맥) 에서 빌드가 가능하며 이러한 환경체크를 검사는 KDoctor를 이용하여 가능합니다.
, KMM에서 필요한 명령줄 도구이므로 KDoctor를 먼저 brew install kdoctor설치 해야 하며 동시에 KDoctor는 빌드 환경이 정상적인지 여부도 감지할 수 있습니다.

다음으로, compose-multiplatform-ios-android-template 을 사용하면 Compose Multiplatform 프로젝트에 androidApp, iosApp, shared라는 세 가지 모듈이 포함됩니다. 여기서 shared는 이름에서 알 수 있듯이 공유 Kotlin 모듈입니다.

현재 Android 스튜디오의 iOS 시뮬레이터에서 Compose Multiplatform을 실행하려면 iosApp 실행 구성을 선택 해야 하며 주로 해당 실행 대상을 선택해야 합니다.

실제 컴퓨터에서 실행해야 하는 경우 먼저 iOS 개발자 계정이 있어야 하며 Xcode에 로그인해야 합니다.

  • 귀하의 계정에서 정보를 얻으십시오TEAM_ID
  • Xcode에 등록된 iOS 장치인 실제 컴퓨터에 연결합니다.

또한 터미널에서 실행하여 kdoctor --team-ids자연스러운 팀 ID 목록을 얻을 수 있습니다.

당연한 얘기지만 Apple 개발자 등록이 되어 있어야 됩니다.

iOS를 실행하기 전, 위에서 언급한 설정이 필요하며TEAM_IDiosApp/Configuration/Config.xcconfig , 파일 아래의 설정을 열고 TEAM_ID안드로이드 스튜디오에서 프로젝트를 다시 열면 iosApp실행 중인 구성에서 등록된 iOS 디바이스를 확인할 수 있습니다.

iOS용 Compose Multiplatform이 공식적으로 출시되는 날을 기대해 보겠습니다.

2021년 2월 24일 수요일

[iOS] @synchronized 배타 제어 (객체 동시접근 방지)

참고: https://dolfalf.tistory.com/145

https://aroundck.tistory.com/4705


가장간단한건 

 // self를 키로 락을 검. 어디선가 self로 락을 건경우 락이 해제될 때까지 여기서 기다리게됨.
@synchronized (self) {
  [_mutableItems addObject:object];
}


보통 이런식으로도 씀.

@implementation MyClass

{

// 잠금시 키로 지정하는 인스턴스를 저장할 위치를 제공합니다.

NSObject * _objectForLock;

}


이것을 init 메소드 등의 어딘가 적절한 위치로 초기화합니다.

- (id) init

{

self = [super init];


if (self)

{

// 잠금시 키로 지정하는 인스턴스를 준비합니다.

_objectForLock = [[NSObject alloc] init];

}

return self;


}


ARC 환경이라면 Objective-C 인스턴스는 필요하지 않을 때 출시되므로 뒤처리가 필요하지 않습니다.


ARC 환경이 아닌 경우는 -dealloc 메소드 등으로 잠금을 확보 한 인스턴스를 release하도록합니다.


@synchronized의 인수로 사용합니다.


@synchronized (_objectForLock)

{


}


Effective Object-C 에서는 

_syncQueue = dispatch_queue_create("com.effectiveobjectivec.syncQueue", NULL); 

이렇게도 쓰라고함

2021년 2월 21일 일요일

[iOS] 개발/테스트 배포용 ipa 간단 생성

Product->Archive->Distribute App -> Developement ->쭉쭉 다음으로 넘기고

실행하는 쪽은 Xcode->Devices and Simulators 에서 ipa던져넣으면 된다.

[Unity] IOS check version

 

요약

OS 버전을 확인하는 방법이 Objective-C라고 귀찮은 방법 밖에없는 것인지라고 생각하고있어, 피곤하고 있으면, 그런 일은 없었기 때문에 소개.

환경

  • MacOS 10.12.6
  • Xcode 9.0.1

종래의 방법

기술 량이 많아 귀찮았.

if ([UIDevice currentDevice] .systemVersion.floatValue> = 11.0) { 
    NSLog (@ "iOS11 이상이야"); 
} else { 
    NSLog (@ "iOS11 미만이야"); 
}

간단한 방법

묘사가 적게된다.

if (@available (iOS 11.0 *)) { 
    NSLog (@ "iOS11 이상이야"); 
} else { 
    NSLog (@ "iOS11 미만이야"); 
}

주의 사항

@available(〜)그리고 다른 조건을 함께 기재하면 warning이 나온다.
중첩하면 괜찮아.

NG

Bool isClose = YES; 
if (@available (iOS 11.0 *) && isClose) { 
    NSLog (@ "iOS11 이상이야"); 
}

OK

Bool isClose = YES; 
if (@available (iOS 11.0 *)) { 
    if (isClose) { 
        NSLog (@ "iOS11 이상이야"); 
    } 
}

중첩없이 쓸 수 있으면 좋겠다.

2021년 2월 11일 목요일

[IOS] GCD, BLOCK 사용 Dispatch Queues 비동기 큐 처리

 Grand Central Dispatch(GCD)는 큐를 동기/비동기로 처리할수 있도록 도와주는 도구다. 쓰레드를 os 가 자동관리 및 분배해준다. 개발자는 큐에 태스크를 생성해서 넣어주면 OS가 자동으로 태스크들을 실행해주는 방식이다.

일단  자바의 쓰레드에 비해 사용하기 쉽다는 거다.

  • Serial Queue : 순서대로 큐의 태스크를 실행한다. 한개가 끝나면 다음 태스크가 실행되는 방식이다. 단 큐는 여러개 만들수 있기 때문에 여러개의 큐에서 동시에 여러태스크를 동시에 (Concurrency)실행할수 있다.
  • Concurrent Dispatch Queue: GDQ라고 불리며 , 여러태스트를 하나의 큐에서 동시에 진행한다. 동시라고 해서 일시에 시작하는건 아니고 큐에 푸시한 순서대로 동시에 실행되는 거다.
Block Syntax

(처리블럭)을 이용하여 콜백함수처럼 사용하는   블럭코딩은 다음과 같이 한다.

    ^{

        NSLog(@"I am Block");

    };;


    void (^myBlock)(void) = ^{

        NSLog(@"This is a Block");

    };

    // invoke

    myBlock();




블럭 생성과 함수에서 람다(인터페이스? 입급함수?) 처럼 이용해보자.

- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view.

    UBPayInterface *interface = [UBPayInterface sharedInstance:FALSE];


    BOOL isInitialized = [interface isInitalized1];


    //---- 1.선언방식

    ^{

        NSLog(@"I am Block");

    };;

    

    // 변수에 대입방법

    void (^myBlock)(void) = ^{

        NSLog(@"This is a Block");

    };

    // 사용

    myBlock();

    

    //---- 2.변수에 파라메터와 리턴값

    // 리턴값 (^변수이름)(파라메터들) = ^(파라메터들) { 리턴값 } 형식이다.

    NSString* (^getParameterAndReturnString)(NSString*, BOOL) = ^(NSString* name, BOOL isTrush){

        NSString* helloYour = nil;

        if (!isTrush) {

            helloYour = [NSString stringWithFormat:@"%@, is a Liar", name];

        }

        

        return helloYour;

    };

    // 사용

    NSLog(@"%@", getParameterAndReturnString(@"kim", FALSE));

    

    //---- 3.블럭은 {} 스코프안에서 처리되기 때문에 외부의 변수를 기본적으로 읽을수 없다. 때문에 __block 키워드를 사용하여 블럭스코프외부의 변수에 제한적으로 접근할수 있다.

    __block int outerVal = 100;

    void (^canReadableOuterVal)(void) = ^(void){

        outerVal = 50;

    };

    // 사용

    canReadableOuterVal();

    NSLog(@"%d", outerVal);

    

    

    //---- 4.2 호출할때는 선언된 파라메터와 같은 형식으로 호출하면 된다.

    //Java 인터페이스라면  useBlockParameterEx(new myInterface() { @Override sumSum(int num1, int num2) {NSLog(@"%d", num1 + num2);} })

    [self useBlockParameterEx:^(int num1, int num2) {

        NSLog(@"%d", num1 + num2);

    }];

    

    

    NSLog(@"%@", isInitialized ? @"초기화 성공" : @"초기화 실패" );

}


//---- 4.1 함수의 파라메터로 선언은 이렇게 한다.(람다처럼)

//Java 인터페이스라면  useBlockParameterEx(MyInterface argMyinterface) { argMyinterface.sumSum(10, 20); }

- (void) useBlockParameterEx: (void (^)(int, int)) sumSum {

    sumSum(10, 20);

}


Dispatch Queues 디스패치큐 .

디스패치큐는 dispatch_get_main_queue(프로그램에서 사용하는 메인큐 싱글, 즉 시리얼 디스패치큐) 와 dispatch_get_global_queue(시스템에서 사용하는 동시성 큐, 콘커런트 큐) 와 프로그래머 직접 만드는 dispatch_queue_create(이 명령으로  쓰레드를 프로그래머만든다) 
이렇게 3종류가 있다.
  1. dispatch_get_global_queue (시스템에서관리)
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 형태로서 우선순위에 의해 High, Default, Low, Background 로 구분할수 있다.
  2. dispatch_get_main_queue (우리 앱에 메인 쓰레드)
  3. dispatch_queue_create (사용자가 생성한 쓰레드)
    dispatch_queue_create("this area is for a log", DISPATCH_QUEUE_SERIAL) 형태이며DISPATCH_QUEUE_SERIAL, DISPATCH_QUEUE_CONCURRENT 두가지 생성옵션과 sync, Async 실행방식으로 구분된다.
A. Serial Dispatch Queue 생성 
순차적으로 실행해야 되는 작업은  DISPATCH_QUEUE_SERIAL옵션으로 큐를 만들고 , 작업을 큐에 넣으면 된다.

  


sync - 릴레이 처럼 출발한 순서대로 

    //---- 5. Serial 큐.

    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);

    dispatch_sync(queue, ^{ NSLog(@"-> 1"); });

    dispatch_sync(queue, ^{ NSLog(@"-> 2"); });

    dispatch_sync(queue, ^{ NSLog(@"-> 3"); });

    

    //---- 5-1. Serial 큐 지연시키기.

    dispatch_time_t pushTime3s = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));

    dispatch_sync(queue, ^{ NSLog(@"-> 5"); });

    dispatch_after(pushTime3s,queue, ^{ NSLog(@"-> 6"); });

    

    //---- 5-2. Serial 큐 지연시키기.

    // 일단 블럭시키고 시간이 걸리는 작업을 하자 8->6 이 예상되지만, 블럭킹처리시간으로 인해 큐에 추가되는 순서는 6->8

    // 시간지연을 주더라도 해당시간에 실행되는것이아니라 해당시간에 큐에 추가하려고 하는거다.

    // 따라서 긴시간 작업하던 7의 중간에 6이 끼어들어추가하려해서 추가됬고, 8이 그다음에 추가된거다.주의해야한다.

    typedef void (^iambloking)(void);

    iambloking blokinghehe = ^{

    NSMutableArray *array = [[NSMutableArray alloc] init];

    for ( long i = 0; i < 100000000; i++ ) {

        [array addObject:[NSNumber numberWithLong:i]];

    }};

    dispatch_sync(queue, ^{ NSLog(@"-> 7");blokinghehe();  }); // 오래걸리는 블럭킹을 부르자

    dispatch_sync(queue, ^{ NSLog(@"-> 8"); });

    //1,2,3,4,5,7(wait),6,8


Async - 마라톤처럼 도착한 순서대로 

    //---- 5. Serial 큐.

    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);

    dispatch_async(queue, ^{ NSLog(@"-> 1"); });

    dispatch_async(queue, ^{ NSLog(@"-> 2"); });

    dispatch_async(queue, ^{ NSLog(@"-> 3"); });

    

    //---- 5-1. Serial 큐 지연시키기.

    dispatch_time_t pushTime3s = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));

    dispatch_async(queue, ^{ NSLog(@"-> 5"); });

    dispatch_after(pushTime3s,queue, ^{ NSLog(@"-> 6"); });

    

    //---- 5-2. Serial 큐 지연시키기.

    // 일단 블럭시키고 시간이 걸리는 작업을 하자 8->6 이 예상되지만, 블럭킹처리시간으로 인해 큐에 추가되는 순서는 6->8

    // 시간지연을 주더라도 해당시간에 실행되는것이아니라 해당시간에 큐에 추가하려고 하는거다.

    // 따라서 긴시간 작업하던 7의 중간에 6이 끼어들어추가하려해서 추가됬고, 8이 그다음에 추가된거다.주의해야한다.

    typedef void (^iambloking)(void);

    iambloking blokinghehe = ^{

    NSMutableArray *array = [[NSMutableArray alloc] init];

    for ( long i = 0; i < 100000000; i++ ) {

        [array addObject:[NSNumber numberWithLong:i]];

    }};

    dispatch_async(queue, ^{

        NSLog(@"-> 7");

        dispatch_async(dispatch_queue_create("innerQ", DISPATCH_QUEUE_SERIAL),  ^{ NSLog(@"-> innerQ"); blokinghehe(); });

    }); // 오래걸리는 블럭킹을 부르자

    dispatch_async(queue, ^{ NSLog(@"-> 8"); });

    //1,2,3,4,5,7(wait),8,6


B. Concurrent Dispatch Queue 생성 
동시에 여러 태스크를 동시다발적으로 실행할수 있다. SERIAL은 한번에 한개의 태스크가 끝나야 다음 태스크로 넘어갔지만, CONCURRENT에서는 전역쓰레드의 여유에 따라서 태스크들이 순서에 상관없이 실행될수있다.  각 태스트는 각자으 ㅣ쓰레드를 생성하여 수행된다.


    
dispatch_queue_t queue = dispatch_queue_create("test"DISPATCH_QUEUE_CONCURRENT);

사용법은 SERIAL과 같다.


C. Group 생성  - 모든 태스크가 끝난는지 판단
태스크들이 모두 끝났는지를 판단하려면 태스크들을 하나의 작업으로 묶어야하는데 group 으로 가능하다. 

   //---- 6. Dispatch Group

    dispatch_queue_t queueG = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_group_t group = dispatch_group_create();


    dispatch_group_async(group, queueC, ^{

        [NSThread sleepForTimeInterval:1];

        NSLog(@"Done: %d", 1);

    });

    

    // 그룹에 추가

    dispatch_group_enter(group);

    //콜백 정의

    typedef void (^blk_t)(void (^callback)(void));

    blk_t callback = ^(void (^callback)(void)){

        NSMutableArray *array = [[NSMutableArray alloc] init];

        for ( long i = 0; i < 35000000; i++ ) {

            [array addObject:[NSNumber numberWithLong:i]];

        }

        callback();

    };

    //콜백호출

    callback(^{

        //콜백 함수로 그룹에 추가한게 끝이라고 하게함

        dispatch_group_leave(group);

    });

    //enter->leave가 끝나야 다음 태스크 실행

    dispatch_group_async(group, queueG, ^{ NSLog(@"Done' %f", 1.5); });


    dispatch_group_notify(group, queueG, ^{

        NSLog(@"All tasks are done!");

    });

    

    dispatch_group_async(group, queueG, ^{

        //[NSThread sleepForTimeInterval:2];

        NSLog(@"Done: %d", 2);

    });

    dispatch_group_async(group, queueG, ^{

       // [NSThread sleepForTimeInterval:1];

        NSLog(@"Done: %d", 3);

    });

    //https://padgom.tistory.com/entry/iOS-%EA%B8%B0%EB%B3%B8-GCDGrand-Central-Dispatch-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0





D. Barrier 특정 지점에서 장벽? 을 쳐서 그부분까지 실행하도록 하고, 다음 태스크들을 기다리게하는거
E. Semaphore 로 지정한 시간만큼 기다리게 할수 있다. 
F. Suspend 잠시 실행을 멈춘다. 다만 태스크들을 계속 추가될수있다. Resume로 복귀.
G. Dicpatch_once 로 싱글턴도 만들수 있다.  queue에 아무리 넣어도 프로그램기동후에는 한번만 실행된다.


2021년 2월 10일 수요일

[ios] object-c 로 framework만들기

 Object-c 로 framework만들기

ios8 부터는 framework형태로 라이브러리 제작이 가능하다. 이를 cocoapod등에 올리면 cocoapod install명령으로 간단하게 누구나 사용할수있는 라이브리를 만들수 있다.


1. 일단 file-> new -> workspace 를  만든다. (MY_IOS_FRAMEWORK폴더로 만들고, my_ios_framework이름의 스페이르를 만들었다)

2.만들면 에디터에 아무것도 없는데, file->new->project를 선택하여 밑의 Framework & library에서 Framework 를 선택한다.
https://github.com/sugoigroup/ios_framework_sample/commit/6e2d9bf1b32b893803468715e9e889e8da260e03

3.Product Name 은 적당하게 입력( myframework ) 

4.다음 화면에서 프로젝터의 폴더를 선택하라고 하는데, 폴더를 아까 만든 workspace 를 선택(MY_IOS_FRAMEWORK)하고 , 중요한건 [ Add to] 에서 아까 만든 워크스페이스를 선택(my_ios_framework)한다.

5. PROJECT 에서 myframework(서류상자)를 선택하고 Build Settings 에서 Architectures -> Build Active Architecture Only 를 No로 한다.(Debug때만 Yes로 하며, 이렇게 하면 빌드시에 연결된 기기에 맞게 아키텍쳐가 구성됨.) 
https://github.com/sugoigroup/ios_framework_sample/commit/9bc32aaa070d65230dbee79cfe33326c10e5d817

6.TARGETS에서 에서 myframework(서류상자) 선택하고 Build Phases 에서 Headers 에 myframework.h 가 public 에 있는지 확인

7. 현재 framework 는 만들어 졌지만, 아무기능도 안하므로 로그라도 찍는 녀석을 만들자. myframework(누런폴더) 에서 File -> new -> file... 선택하고 [ Cocoa Touch Class]를 선택해서 "MyLogger "(NSObject - Object-c) 입력하여 파일을 만들자.
https://github.com/sugoigroup/ios_framework_sample/commit/015d51bfde20328e82403096ac4566ef6a3b9307

8. MyLogger.h(헤더파일) 과MyLogger.m(바디화일)에 할일들을 넣어보자. 이 프레임워크를 이용하는 쪽에서 (싱글천) 객체를 초기화시에 로그를 찍겠다고 true  를 설정하면 로그가 찍히는 작업을 만들어보자.
https://github.com/sugoigroup/ios_framework_sample/commit/45f3f30468762e320b9a6f50586bf11fcb961330
 

9. MyLogger를 만들긴 했어도 외부에서는 볼수 없는 상태이기 때문에 , MyLogger.h 를 선택하여, 오른쪽의 Target Membership 영역에서 myframework: Project 로 되어있는 부분을 myframework:Public으로 바꾸자.
그리고 myframework.h 의 맨밑줄에 #import <MyLogger/MyLogger.h> 를 추가하자. 실제로는 이거다 . #import <myframework/MyLogger.h>
https://github.com/sugoigroup/ios_framework_sample/commit/0039f77376cdbae22a158f5af39a85081bf54d6a

10. 이제 Product > Build 해보면  왼쪽의 Products(노란색)밑에 myfamework.framework 파일이 생긴다.(원래 있었지만 빨간색이었을지도 )

11.  myfamework.framework를 사용할 사용자앱(customerformyframework)을 만들자. File->new->Project 에서 간단한 앱을 생성한다.(폴더는 MY_IOS_FRAMEWORK 하위에 생성되도록 했다. 딴데두기 귀찮아서..)
https://github.com/sugoigroup/ios_framework_sample/commit/9d6db6236bed8f1b8ce64b716a7c4710cc292c92

12.여기에 이제 myframework.framework를 넣어야 하는데, 그냥 myfamework.framework 파일을 잡고 새로열게된 customerformyframework 편집창의 왼쪽 맨위의 파란색Xcode아이콘 밑에 넣자. ( Copy Items if needed 선택하자.)

13. ViewController.m 파일에서 사용해보자.
아! customerformyframework에서  TARGETS > General > Frameworkds, Libraties 에 보면 Embed 가 Do Not Embed 로 되어있는데,  Embed Without Signing 으로 선택하자.
https://github.com/sugoigroup/ios_framework_sample/commit/034dd5315c94dbb7556003c30b15d0a109f9b617

#import "ViewController.h"

#import <myframework/myframework.h>


@interface ViewController ()


@end


@implementation ViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view.

    

    MyLogger *mylogger = [MyLogger sharedInstance:TRUE];

    [mylogger printMyLog:@"taeho"];

}



@end



14. 실행하면 로그가 찍힌다..


2021-02-10 23:59:56.856301+0900 customerformyframework[82872:2892194] Log your name: taeho


MyLogger *interface = [MyLogger sharedInstance:FALSE]; 를 FALSE로 하면 안찍힌다.

2021년 1월 19일 화요일

Unity3d 에서 네이티브 IOS 코드 불러내서 사용하기-심플

 참고사이트:https://twnkls.com/en/blogs/howto-native-android-plugins-for-unity3d-2/

한번보면 알게되는 강좌 :https://www.youtube.com/watch?v=zP5mjHzJR-o (Creating an iOS Plugin for Unity3D)


1.일단 유니티 프로젝트를 생성한다.

2.Assets 목록에 
- Plugins
  -- iOS
- Scripts 
가 있는지 확인하고 없으면 생성한다.

3. IOS폴더에 "ItsYourPlugin"이라는 스크립트를 생성하자.
이 스크립트는 생성하면 cs이지만, IOS연동용으로 하기위해  .mm 확장자로 바꿔야 한다.

4.바꿨다면 아이콘이 퍼즐조각으로 바뀐다. ( 난 유툽강좌대로 MyPlugin으로 했다)


5.이제 저걸 더블클릭하면 Xcode가 에디터에 저 파일의 내용이 뜬다. cs 용 내용이므로 이걸 다 지우고 아래처럼 object-c코드로 바꾼다.
이 파일에는 헤더(보통 .h파일)와 바디(보통 .m)파일의 내용을 구분없이 한 파일에 쓰도록 한다.
ItsYourPlugin는 기본적으로 다음과 같이 구성한다.

#import <Foundation/Foundation.h>


// 머리,xcode에서 .h 라고 있던녀석들
@interface MyPlugin: NSObject
{
}
@end

// 몸통,xcode에서 .m 라고 있던녀석들
@implementation MyPlugin

@end

// 꼬리,Unity에서 보여줄 녀석들
extern "C"
{

}


6. object-c 클래스를 unity 에서 불러내서 연동하려면 (객체화) 라는 것을 유니티가 할텐데,  유니티가 object-c쪽의 함수를 호출(정확히는 extern c를 통해 호출) 할때 마다 객체를 생성하면 메모리가 미쳐나갈수 있으니 싱글톤으로 만들어지도록 object-c쪽에 코드를 넣어야한다. 
(게임 루프는 1초에 30-60 번! 이나 호출하기때문이다!!)

// 몸통,xcode에서 .m 라고 있던녀석들
@implementation MyPlugin

+(MyPlugin*) sharedInstance       //현재객체(MyPlugin)을 돌려받는 싱글톤 함수 선언
{

static
MyPlugin *_sharedInstance; //스택틱 빈객체선언
static dispatch_once_t onceToken; //APP 라이프 사이클에 마추어 단 한번만 실행되로록 보장 이라네.. dispatch_once(&onceToken, ^{ NSLog(@"Create Instance IOS"); _sharedInstance = [[MyPlugin alloc] init]; }); // obejct-c 의 싱글톤 패턴작성패턴이다. 토큰이 없으면 MyPlugin 객체생성 후 스택틱 변수에넣음 return _sharedInstance; //스택틱 변수를 돌려줌.잉? 그럼왜 _s } @end


7.자, 이제 유툽강좌에 있던 내용대로 써보자

#import <Foundation/Foundation.h>

@interface MyPlugin: NSObject
{

    NSDate *creationDate;
}
@end

@implementation MyPlugin

+(MyPlugin*) sharedInstance
{
    static MyPlugin *_sharedInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"Create Instance IOS");
        _sharedInstance = [[MyPlugin alloc] init];
    });
    
    return _sharedInstance;
}


-(id)init
{
    self = [super init];
    if (self)
        [self initHelper];
    return self;
    
}

-(void)initHelper
{
    NSLog(@"InintHelper callsed");
    creationDate = [NSDate date];
}

-(double)getElapsedTime
{   
    // 클래스 초기화 때 실행하는 initHelper 에서 creationDate(시작시간이겠지)을 만들고, timeIntervalSinceDate로 실행시간을 구한다. 
    return [[NSDate date] timeIntervalSinceDate:creationDate];
}
@end


extern "C"
{
double IOSgetElapsedTime() { //유니티에서는 이 함수를 호출할것이다.싱글톤객체 얻은후 getElapseTime 반환값을 유니티쪽에 던져줌.
    return [[MyPlugin sharedInstance] getElapsedTime];
}
}

8.일단 object-c쪽은 준비가 되었다. 이제 Unity의 스크립트 등에서 object-c에서 만들어둔 함수 IOSgetElapsedTime 를 불러내보자.
Assets의 Scripts폴더밑에 PluginTest라는 스크립트를 생성하고 아래처럼 넣자

using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;

public class PluginTest : MonoBehaviour
{
#if UNITY_IOS
	[DllImport("__Internal")] 
    //DllImport는 C#에서 다른 프로그램을 불러낼때 쓰인다
    private static extern double IOSgetElapsedTime(); //아까 object-c에서 만든함수랑 같은 이름을 지정한다.
#endif
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Elapsed" + getElapsedTime());
    }

    int frameCounter = 0;
    // Update is called once per frame
    void Update()
    {
        frameCounter++;
        if (frameCounter >= 5) {
        	Debug.Log("Tick" + getElapsedTime());
        	frameCounter = 0;
        }
    }

    double getElapsedTime() { //Start랑 Update에서 불리는 함수다. IOS일때만 불리도록 했다.
    	if (Application.platform == RuntimePlatform.IPhonePlayer) 
    	   return IOSgetElapsedTime();
    	return 0;
    }
}

9.자 이 스크립트를 카메라에 붙이자. 카메라는 항상있으니까.. 그럼 씬이 시작될때 start->update->update->update..... 하면서 실행후 지난시간들이 Log에 찍힌다.

10.이제   유니티 프로젝트를 빌드해 보자


10.빌드하면 Unity를 Xcode에서 빌드할수 있도록 저장폴더를 물어보고, 폴더를 선택했다면, Xcode가 열리면서 현재작업중인 모든 유티니관련 자료,라이브러리가 포함된 프로젝트가 열린다.

11.위에서 작성한(ItsYourPlugin.mm)의 내용이 바뀌거나, unity에서 관련스크립트가 변경되었다면 항상 command+b를 눌러서 과정10에서 생성된 프로젝트에 동일하게 반영되도록 해야한다.



Github : https://github.com/sugoigroup/cuddly-spork.git
나중에 내가 보려요..