레이블이 object-c인 게시물을 표시합니다. 모든 게시물 표시
레이블이 object-c인 게시물을 표시합니다. 모든 게시물 표시

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월 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
나중에 내가 보려요..