반응형

2D 충돌처리

(1) 선과

 -  Line 직선의 방정식을 구함.          
    P = P1 + u(P2 - P1), P' = P3 + v(P4 - P3)

    교차하는 점에선 P == P'이므로,              
    P1 + u(P2 - P1) = P3 + v(P4 - P3)

    각각 x y 대해 정리                          
    x1 + u(x2 - x1) = x3 + v(x4 - x3)
    y1 + u(y2 - y1) = y3 + v(y4 - y3)

    두 식을 이용해, u v 대해 풀어낸다.  
    u = ((x4-x3)*(y1-y3)-(y4-y3)*(x1-x3)) / ((x2-x1)*(y4-y3)-(x4-x3)*(y2-y1))
    v = ((x2-x1)*(y1-y3)-(y2-y1)*(x1-x3)) / ((x2-x1)*(y4-y3)-(x4-x3)*(y2-y1))

    두 선의 각각의 좌표를 이용해 u v 값을 구할 있음.
    이 u v 0이면 수평, 0 < u < 1이고 0 < v < 1이면 교점이 있는 것임. u v 1보다 크면, 만나지 않는 것임.
구한 u v 직선의 방정식에 대입하면교점의 좌표도 구할 있음.

 

(2) 선과 사각형

 - 사각형의 선분에 대해 선과 충돌을 검사.

float inputRotation = MathHelper.ToRadians(degree);
Rectangle destRect = new Rectangle(200, 200, 200, 200);
Vector2 vOrg = new Vector2(1, 0);

vOrg = Vector2.Transform(vOrg, Matrix.CreateRotationZ(inputRotation));
  
BoundingBox box = new BoundingBox(new Vector3(destRect.Left, destRect.Top, 0.0f),
                                  new Vector3(destRect.Right, destRect.Bottom, 0.0f));
Ray ray = new Ray(new Vector3(vStart, 0.0f), new Vector3(vOrg, 0.0f));

float? result = box.Intersects(ray);

if (result != null && result <= lineLength)
{

   // 충돌

}

 

3D에서 충돌을 감지하는 BoundingBox Ray 2D에서 사용하도록 처리한 것입니다.

3차원을 2차원으로 줄이기 위해 Z 값을 0.0f 설정했구요.

참고로 ray boundingbox 충돌의 결과는 거리가 나오는 데요.

충돌을 하지 않을 경우에는 null 나오고, 충돌을 하면 충돌된 거리가 나옵니다.

 

충돌된 거리가 직선의 길이보다 작아야 충돌로 인지하게 처리하면 끝이 납니다.

 

(3) 선과

 - 원의 중점Pc 에서 (P1->P2) 수직하는 (최단거리) 만든다선과 수선이 만나는 교점이 선의 범위 안에 있으면 충돌

   P = P1 + u(P2 - P1) -> P 교점이라 하면, (Pc - P) dot (P2 - P1) = 0(내적이 0이면 직각)

   식을 풀면 u = (Pc - P1) dot (P2 - P1) / (P2 - P1) dot (P2 - P1)

   u < 0이면, P1 원의 중점으로부터 최단 거리(u == 0 이면 P1 수직인 좌표)

   u > 1이면, P2 원의 중점으로부터 최단 거리(u == 1 이면 P2 수직인 좌표)

   u값을 처음의 식에 대입하면, 교점 P 나옴

   교점 P에서 원의 중점까지의 거리가 원의 반지름보다 작으면 충돌

 

(4) 사각형과 사각형

 - 사각형을 R1 R2라고 했을때, R1 네점이 R2 포함되는지, R2 네점이 R1 포함되는지 검사.

   하나라도 포함되면, 충돌

 

(5) 사각형과

 - 원의 중점에서 사각형의 꼭지점에 대한 거리가, 원의 반지름보다 작거나 같은 점이 하나라도 있으면 충돌

 

(6) 원과

 - 원의 중점간의 거리가 원의 반지름의 합보다 작거나 같으면 충돌.

 

 

직선의 교차점을 구하는 알고리즘

글은 선분의 교차점을 구하는 알고리즘이 작업에 필요해서 작성해둔 글이다. 참고로, 예전에 두선분의 교차점을 구하는 자체가 쉬울 것으로 생각하고 흔히 생각하는 기울기, y 절편을 이용하여 접근하려고 하였다. 이는 상당히 비효율적 방법이였고 조금 효율적인 방법으로 접근하였다


먼저 직선의 방정식으로써, 기울기와 절편으로 나타내지 말고, t 매개변수를 이용해 나타내면 다음과 같다. 

P1 P2 직선의 시작점과 끝점을 나타내며, t 범위는 0에서 1까지이다. (P1, P2에서 1, 2 아래첨자로 생각하기 바란다)

선의 식을 알았으니, 이제 두선의 교점을 구해보는 것으로 응용해보자. 먼저 아래 그림을 보자.

 

 

Line1 P1 P2 이루어져 있으며, Line2 P3 P4 이루어져 있다. 두개의 라인을 식으로 표현해보면 다음과 같다.

 

 

이미 알겠지만, t s 0에서 1부터의 값이며, 두선의 교점은 두선의 공통된 값이므로 P(t) P(s) 같으므로 위의 2개의 식은 아래의 1개의 식으로 나타낼 있다.

 ( 1 - t ) P1 + tP2 = ( 1 - s ) P3 + sP4

 

 

다시 위의 식을 x, y 분리해보면 아래와 같은 두개의 식들로 분리된다.

 

x로 분리  

P1 = x1; P2 = x2; P3 = x3; P4 = x4;

 

(1-t)x1 + tx2 = (1-s)x3 + sx4

x1 - tx1 + tx2 = x3 -sx3 + sx4

x1 + t (x1 + x2) = x3 + s (x4 - x3)

 

y로 분리 

P1=y1; P2 = y2; P3=y3; P4=y4;

y1 + t (y1 + y2) = y3 + s (y4 - y3)

 

 

위의 식을 t s 대해서 정리를 해보면 다음과 같다.

 

 

, 위의 t s 두선이 서로 만날때의 값이므로, 최종적으로 두선의 교점은 다음과 같이 나타낼 있다.

위의 x, y 우리가 구하고자하는 직선의 교점이다

마지막으로 t s 대해 정리해 보도록 하자.


s
t 값이 0 1 사이를 벗어나는 경우, 선은 교차하지 않는다고 판정해야 한다. 그리고 s t 구하는 공식에서 분모가 0 경우 선은 평행하다는 의미이므로 교점은 존재하지 않다. 분모와 분자 모두 0 경우 선은 동일한 선이다.


아래의 코드는 위의 설명을 토대로 작성하였다.

bool checkCross(const CPoint& AP1, const CPoint& AP2, const CPoint& BP1, const CPoint& BP2, CPoint* IP)

{
    double t;

    double s; 

    double under = (BP2.y-BP1.y)*(AP2.x-AP1.x)-(BP2.x-BP1.x)*(AP2.y-AP1.y);

    if(under==0) return false;

    double _t = (BP2.x-BP1.x)*(AP1.y-BP1.y) - (BP2.y-BP1.y)*(AP1.x-BP1.x);

    double _s = (AP2.x-AP1.x)*(AP1.y-BP1.y) - (AP2.y-AP1.y)*(AP1.x-BP1.x); 

    t = _t/under;

    s = _s/under; 


    if(t<0.0 || t>1.0 || s<0.0 || s>1.0) return false;

    if(_t==0 && _s==0) return false; 



    IP->x = AP1.x + t * (double)(AP2.x-AP1.x);

    IP->y = AP1.y + t * (double)(AP2.y-AP1.y);

    return true;
}

 

2020/12/15 - [iOS/Tips] - 디버깅 차단 처리 (Anti Debug)

2020/12/14 - [iOS/Tips] - bundle id 알아내기

2020/12/12 - [AI/Algorithm] - 2D 충돌처리

2020/12/11 - [iOS/Swift] - UIViewController 스위칭

2020/12/11 - [개발노트] - PlantUML 설치 (Mac OS X)

2020/12/11 - [개발노트] - 특수문자 발음

2020/12/10 - [iOS/Objective-C] - 웹뷰에서 javascript 함수 동기식 호출

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (2/2)

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (1/2)

2020/12/10 - [iOS/Tips] - Custom UserAgent 설정

2020/12/10 - [iOS/Tips] - CocoaPods 설치 및 제거

2020/12/10 - [iOS/Tips] - Clang diagnostic 경고 무시하기

2020/12/10 - [개발노트] - Bluetooth UUID

2020/12/08 - [개발노트] - 모바일 앱 메모리덤프 이슈 해결방법

2020/12/08 - [프로그래밍/Java Script] - Android, iOS 앱 설치여부 체크 및 스토어 이동

 

반응형

'개발 > AI,ML,ALGORITHM' 카테고리의 다른 글

MNIST 데이터셋 다운로드  (0) 2023.07.19
Neural Network (XOR)  (0) 2022.11.18
Generic algorithm  (0) 2020.05.19
neural network  (0) 2020.05.19
minimax full search example  (0) 2020.05.19
블로그 이미지

SKY STORY

,
반응형

손쉬운 업데이트를 위해 대부분의 회사에서 하이브리드 앱으로 개발을 합니다.

이 과정에 특정 서비스의 경우 웹뷰를 따로 구성해야하는 상황이 발생합니다.

예를들어, AViewController, BViewController와 같이 UIViewController를 상속받는 ViewController를 따로 생성하여 웹뷰를 구성하게 됩니다. 이러한 구성에 따로 생성된 뷰컨트럴러간 스위칭이 필요한 경우가 발생합니다.

+ UINavigationController

   - AViewController

   - BViewController

   - CViewController

위와 같은 경우 마지막에 추가된 CViewController가 화면에 출력됩니다.

UINavigationController의 뷰컨트럴러 배열의 순서를 변경하면 원하는 뷰컨트럴러를 최상단으로 올릴 수 있습니다.

다음은 해당 기능을 구현한 클래스입니다.

extension UINavigationController {
	// 주어진 UIViewController를 제거합니다.
    func removeVC(_ kindClass: AnyClass) {
        self.viewControllers = self.viewControllers.filter {!$0.isKind(of:kindClass)}
    }
    
    // 주어진 UIViewController가 존재하는지 체크
    func containsVC(_ kindClass: AnyClass) -> Bool {
        return self.viewControllers.contains(where: {$0.isKind(of:kindClass)})
    }
    
    // 주어진 UIViewController를 최상위에 출력되도록 합니다.
    func setTopVC(_ kindClass: AnyClass) -> UIViewController? {
        var stack: [UIViewController] = self.viewControllers
        var index: Int = 0
        for vc in stack {
            if vc.isKind(of: kindClass) {
                stack.remove(at: index)
                stack.append(vc)
                self.viewControllers = stack
                return vc
            }
            index += 1
        }
        return nil
    }
    
    // 주어진 UIViewController를 존재하는 경우 최상위에 출력되도록 합니다.
    func activateVC(_ kindClass: AnyClass) {
        if containsVC(kindClass) {
            _ = setTopVC(kindClass)
        }
    }
}

extension UIViewController {
	// 옵져버 추가
    func addObserver(_ aSelector: Selector) {
        NotificationCenter.default.addObserver(self,
                                               selector: aSelector,
                                               name: NSNotification.Name(self.theClassName),
                                               object: nil)
    }
	
    // 옵져버 삭제
    func removeObserver() {
        NotificationCenter.default.removeObserver(self)
    }
    
    // 타깃 뷰컨트럴러로 데이터 전달 
    func post(_ targetClassName: String, _ userInfo: [AnyHashable : Any], _ delay: Double = 0.0) {
        let delayTime: Double = (delay < 0) ? 1.0 : delay
        Timer.scheduledTimer(withTimeInterval: delayTime, repeats: false, block: {_ in
            NotificationCenter.default.post(name: NSNotification.Name(targetClassName),
            object: nil,
            userInfo: userInfo)
        })
    }
}



//
// BViewController
// 

override func viewDidLoad() {
    super.viewDidLoad()
    addObserver(#selector(onCommand))
    ... 중간 생략 ...
}
        
deinit {
    removeObserver()
}

... 중간 생략 ...

@objc func onCommand(notification: Notification) {
    guard notification.name.rawValue == self.theClassName else { return }
    guard let userInfo = notification.userInfo else { return }
    
    let name = userInfo["name"] as? String ?? ""
    if name == "이벤트이름" {
        let paramString = userInfo["data"] as! String
        self.sendScript(name: "이벤트이름", result: paramString)
    }
    else {
        //self.userMethod = name
        //self.userInfo = userInfo["data"] as! Dictionary <String, Any>
    }
}

    

//
// 사용 방법
// : 아래 내용은 CViewController에서 BViewController로 이벤트 데이터를 전달 및 화면 스위칭한다.
//

// BViewController에 이벤트 데이터 정보 전달
post("BViewController", ["name" : "이벤트이름", "data" : "전달할 데이터 정보"])

// 0.5초 딜레이 주어 웹뷰 로딩 시간을 주었다.
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
	self.navigationController?.activateVC(BViewController.self)
}

 

2020/12/11 - [iOS/Swift] - UIViewController 스위칭

2020/12/11 - [개발노트] - PlantUML 설치 (Mac OS X)

2020/12/11 - [분류 전체보기] - Tones And I - Dance Monkey

2020/12/11 - [lyrics] - Beyonce - Halo

2020/12/11 - [개발노트] - 특수문자 발음

2020/12/10 - [iOS/Objective-C] - 웹뷰에서 javascript 함수 동기식 호출

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (2/2)

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (1/2)

2020/12/10 - [iOS/Tips] - Custom UserAgent 설정

2020/12/10 - [iOS/Tips] - CocoaPods 설치 및 제거

2020/12/10 - [iOS/Tips] - Clang diagnostic 경고 무시하기

2020/12/10 - [개발노트] - Bluetooth UUID

2020/12/08 - [개발노트] - 모바일 앱 메모리덤프 이슈 해결방법

2020/12/08 - [프로그래밍/Java Script] - Android, iOS 앱 설치여부 체크 및 스토어 이동

2020/08/21 - [Android/Tips] - aab파일 apk파일로 변환

반응형

'개발 > iOS' 카테고리의 다른 글

디버깅 차단 처리 (Anti Debug)  (0) 2020.12.15
bundle id 알아내기  (0) 2020.12.14
웹뷰에서 javascript 함수 동기식 호출  (0) 2020.12.10
Fat Static Library 빌드 (2/2)  (0) 2020.12.10
Fat Static Library 빌드 (1/2)  (1) 2020.12.10
블로그 이미지

SKY STORY

,
반응형

시퀀스다이어그램 작업시 자주 사용 중인데 Visual Studio Code에서 사용 중입니다.

물론 플러그인으로 제공되므로 현재 작업중이신 개발툴에 설치 가능합니다.

 

Visual Studio Code 설치
https://code.visualstudio.com/download

Extensions 메뉴 선택 후 ‘PlantUML’ 검색 및 설치

plantuml.jar 다운로드 
https://sourceforge.net/projects/plantuml/files/plantuml.jar/download

brew 설치
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/ install/master/install)"

java 설치
brew cask install java

plantuml.jar 파일 로컬 폴더에 복사
mkdir -p /usr/local/Cellar/plantuml && cp ~/Downloads/plantuml.jar /usr/local/ Cellar/plantuml

Graphviz 설치 
http://www.graphviz.org/download/ 
brew install graphviz

숨겨진 파일 보이기
Ctrl + Shift + .

sudo ln -s /usr/local/Cellar/plantuml /usr/local/bin/plantuml

~/.zshrc 파일에 환경 설정
# Add environment variable JAVA_HOME
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-14.0.2.jdk/Contents/ Home
export PATH=$JAVA_HOME:$PATH

# Add environment variable PLANTUML_JAR
export PLANTUML_JAR=/usr/local/Cellar/plantuml/plantuml.jar export PATH=$PLANTUML_JAR:$PATH

# Add environment variable GRAPHVIZ_DOT export GRAPHVIZ_DOT=/usr/local/bin/dot export PATH=$GRAPHVIZ_DOT:$PATH

 

콘솔창 재실행 후 환경설정 재로드
source ~/.zshrc

저장방법 :
Command + Shift + P
PlantUML: Export Current File Diagram 
선택 png 또는 svg를 선택

 

참고자료 :

가이드 문서 : http://plantuml.com/ko/guide

Apple fonts 다운로드 : https://developer.apple.com/fonts/

 

 

2020/12/16 - [개발노트] - Code 128 Barcode의 Check Digit 계산방법

2020/12/15 - [iOS/Tips] - 디버깅 차단 처리 (Anti Debug)

2020/12/14 - [iOS/Tips] - bundle id 알아내기

2020/12/12 - [AI/Algorithm] - 2D 충돌처리

2020/12/11 - [iOS/Swift] - UIViewController 스위칭

2020/12/11 - [개발노트] - PlantUML 설치 (Mac OS X)

2020/12/11 - [개발노트] - 특수문자 발음

2020/12/10 - [iOS/Objective-C] - 웹뷰에서 javascript 함수 동기식 호출

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (2/2)

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (1/2)

2020/12/10 - [iOS/Tips] - Custom UserAgent 설정

2020/12/10 - [iOS/Tips] - CocoaPods 설치 및 제거

2020/12/10 - [iOS/Tips] - Clang diagnostic 경고 무시하기

2020/12/10 - [개발노트] - Bluetooth UUID

2020/12/08 - [개발노트] - 모바일 앱 메모리덤프 이슈 해결방법

 

반응형

'개발 > Note' 카테고리의 다른 글

RSA 암복호화  (0) 2020.12.17
Code 128 Barcode의 Check Digit 계산방법  (0) 2020.12.16
특수문자 발음  (0) 2020.12.11
Bluetooth UUID  (0) 2020.12.10
모바일 앱 메모리덤프 이슈 해결방법  (0) 2020.12.08
블로그 이미지

SKY STORY

,

특수문자 발음

개발/Note 2020. 12. 11. 09:53
반응형

별것 아니지만 중요한 것이죠. 정리해 봅니다.

The english name of special characters

# = pound sign (American English), hash sign (British English)

£ = pound sign (British English)

@ = at sign

$ = dollar sign

% = percent sign

^ = caret [kǽrit]

& = ampersand [ǽmpərsӕnd]

* = asterisk [ǽstərìsk]

~ = tilde [tíldə]

! = exclamation mark [èkskləméiʃən][maːrk]

() = parentheses [pərénðiziz]  -  parenthesis [pərénθisis]

- = hyphen [háifən]

_ = underscore [Λndərskɔ̀ːr---´]

+ = plus sign

= = equals sign

[] = square brackets[brǽkit]

{} = curly brackets (is there something more "official"? braces?)

\ = backslash

/ = slash, solidus  [slæʃ], [sάlidəs]

<> = angle brackets

¶ = paragraph mark, pilcrow sign [pǽrəgrӕf] [pílkrou]

§ = section sign

= copyright sign

= Yen sign [jen]

= cent sign

º = degree symbol, ordinal indicator

× = multiplication sign [mΛltəplikéiʃən] 

÷ = division sign

 

반응형
블로그 이미지

SKY STORY

,
반응형

UIWebview에서 WKWebview로 변경하면서 js함수 호출시 비동기식으로 호출되는 것을 알 수 있다.

그런데 이전 웹 코드가 동기식으로 해야 동작하는 경우가 생길 수 있다.

이 경우 아래와 같이 동기식으로 호출되도록 처리할 수 있다.

@interface WKWebView(SynchronousEvaluateJavaScript)
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
@end

@implementation WKWebView(SynchronousEvaluateJavaScript)

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
{
    __block NSString *resultString = nil;
    __block BOOL finished = NO;

    [self evaluateJavaScript:script completionHandler:^(id result, NSError *error) {
        if (error == nil) {
            if (result != nil) {
                resultString = [NSString stringWithFormat:@"%@", result];
            }
        } else {
            NSLog(@"evaluateJavaScript error : %@", error.localizedDescription);
        }
        finished = YES;
    }];

    while (!finished)
    {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }

    return resultString;
}
@end

/*
[ 사용 방법 ]
NSString *msg = @"test message";
NSString *param = [NSString stringWithFormat:@"alert('%@')", msg];
[self.webView stringByEvaluatingJavaScriptFromString:param];
*/

 

2020/12/10 - [iOS/Objective-C] - 웹뷰에서 javascript 함수 동기식 호출

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (2/2)

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (1/2)

2020/12/10 - [iOS/Tips] - Custom UserAgent 설정

2020/12/10 - [iOS/Tips] - CocoaPods 설치 및 제거

2020/12/10 - [iOS/Tips] - Clang diagnostic 경고 무시하기

2020/12/10 - [개발노트] - Bluetooth UUID

2020/12/08 - [개발노트] - 모바일 앱 메모리덤프 이슈 해결방법

2020/12/08 - [프로그래밍/Java Script] - Android, iOS 앱 설치여부 체크 및 스토어 이동

2020/08/21 - [Android/Tips] - aab파일 apk파일로 변환

2020/08/11 - [iOS/Swift] - WKWebView 화면 출력 완료 이벤트

2020/08/06 - [iOS/Tips] - 개발관련 폴더 경로

2020/07/19 - [Android/Tips] - 안드로이드 원격 디버깅 방법

2020/07/18 - [Android/Tips] - Cannot convert string value 'JETPACK_COMPOSE' to an enum value of type 'com.android.builder.model.AndroidGradlePluginProjectFlags$BooleanFlag' (valid case insensitive values: APPLICATION_R_CLASS_CONSTANT_IDS, TEST_R_CLASS_CONSTANT_IDS, TRANSITIVE_R_CLASS)

2020/07/18 - [Android/Tips] - OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended

반응형

'개발 > iOS' 카테고리의 다른 글

bundle id 알아내기  (0) 2020.12.14
UIViewController 스위칭  (0) 2020.12.11
Fat Static Library 빌드 (2/2)  (0) 2020.12.10
Fat Static Library 빌드 (1/2)  (1) 2020.12.10
Custom UserAgent 설정  (0) 2020.12.10
블로그 이미지

SKY STORY

,
반응형

이번에는 Fat Static Library만드는 작업을 스크립트로 처리하여 자동화 처리하는 방법입니다.

 

Fat Static Library(이하 Fat 라이브러리) 빌드 자동화  스크립트 사용 방법

1. Xcode의 Build Phases에서 스크립트 추가

2. 아래 스크립트 내용을 붙여넣기 한다.

##############################################

#

# Fat static library

#

# Automatically create cross-platform (simulator + device) 

# static libraries for Objective C / iPhone / iPad.

#

# added by netcanis 2018.10.26 

#############################################

set -e

set -o pipefail



# Get BaseSdk version

SDK_VERSION=$(echo ${SDK_NAME} | grep -o '\d\{1,2\}\.\d\{1,2\}$')



# Get build type (Device or Simulator).

if [ ${PLATFORM_NAME} = "iphonesimulator" ]

then

OTHER_SDK_TO_BUILD=iphoneos${SDK_VERSION}

else

OTHER_SDK_TO_BUILD=iphonesimulator${SDK_VERSION}

fi



if [ "true" == ${ALREADYINVOKED:-false} ]

then

echo "RECURSION"

exit 0;

fi





# Building

export ALREADYINVOKED="true"



xcodebuild -configuration "${CONFIGURATION}" -project "${PROJECT_NAME}.xcodeproj" -target "${TARGET_NAME}" -sdk "${OTHER_SDK_TO_BUILD}" ${ACTION} RUN_CLANG_STATIC_ANALYZER=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" SYMROOT="${SYMROOT}"



ACTION="build"



CURRENTCONFIG_DEVICE_DIR=${SYMROOT}/${CONFIGURATION}-iphoneos

CURRENTCONFIG_SIMULATOR_DIR=${SYMROOT}/${CONFIGURATION}-iphonesimulator

CREATING_UNIVERSAL_DIR=${SYMROOT}/${CONFIGURATION}-universal



# Remove previous build floder.

rm -rf "${CREATING_UNIVERSAL_DIR}"

mkdir "${CREATING_UNIVERSAL_DIR}"



# Make universal static library.

xcrun -sdk iphoneos lipo -create -output "${CREATING_UNIVERSAL_DIR}/${EXECUTABLE_NAME}" "${CURRENTCONFIG_DEVICE_DIR}/${EXECUTABLE_NAME}" "${CURRENTCONFIG_SIMULATOR_DIR}/${EXECUTABLE_NAME}"



echo "Build complete!"

 

3. 빌드 설정을 ‘Release’로 설정한 후 빌드.

 

4. 빌드시 스크립트를 통해 디바이스와 시뮬레이터 빌드를 하며 ‘Release-universal’폴더에
두 빌드에 대한 Fat 라이브러리를 생성하여 준다.

5. ‘Release-universal’ 폴더에 생성된 Fat라이브러리 ‘libXXX.a’를 배포한다.

 

주의 : 빌드시 적용이 안될 경우 시뮬레이터 빌드를 한번 실행한 뒤 다시 시도해 봅니다.

 

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (2/2)

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (1/2)

2020/12/10 - [iOS/Tips] - Custom UserAgent 설정

2020/12/10 - [iOS/Tips] - CocoaPods 설치 및 제거

2020/12/10 - [iOS/Tips] - Clang diagnostic 경고 무시하기

2020/12/10 - [개발노트] - Bluetooth UUID

2020/12/08 - [개발노트] - 모바일 앱 메모리덤프 이슈 해결방법

2020/12/08 - [프로그래밍/Java Script] - Android, iOS 앱 설치여부 체크 및 스토어 이동

2020/08/21 - [Android/Tips] - aab파일 apk파일로 변환

2020/08/11 - [iOS/Swift] - WKWebView 화면 출력 완료 이벤트

2020/08/06 - [iOS/Tips] - 개발관련 폴더 경로

2020/07/19 - [Android/Tips] - 안드로이드 원격 디버깅 방법

2020/07/18 - [Android/Tips] - Cannot convert string value 'JETPACK_COMPOSE' to an enum value of type 'com.android.builder.model.AndroidGradlePluginProjectFlags$BooleanFlag' (valid case insensitive values: APPLICATION_R_CLASS_CONSTANT_IDS, TEST_R_CLASS_CONSTANT_IDS, TRANSITIVE_R_CLASS)

2020/07/18 - [Android/Tips] - OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended

2020/07/17 - [iOS/Tips] - 웹에서 iOS 앱 설치여부 체크

반응형

'개발 > iOS' 카테고리의 다른 글

UIViewController 스위칭  (0) 2020.12.11
웹뷰에서 javascript 함수 동기식 호출  (0) 2020.12.10
Fat Static Library 빌드 (1/2)  (1) 2020.12.10
Custom UserAgent 설정  (0) 2020.12.10
CocoaPods 설치 및 제거  (0) 2020.12.10
블로그 이미지

SKY STORY

,
반응형

정적라이브러리 생성후 배포 시 시뮬레이터로 작업하는 프로젝트의 경우 라이브러리에 해당 아키텍쳐가 포함되어있지 않아 실행할 수 없는 상황이 발생하곤 합니다. 이럴경우 생성된 정적라이브러리에 해당 아키텍처를 포함시켜줄 수 있습니다.

아래의 과정은 배포하는 정적라이브러리를 사용하는 프로젝트에서 시뮬레이터 빌드가 가능하도록 Fat Static Library를 생성하는 방법입니다.

Fat Static Library(이하 Fat 라이브러리) 생성 순서

1. Device 용 빌드
빌드 패스에 ’Release-iphoneos’ 폴더에  저장 됨.

2. Simulator 용 빌드
빌드 패스에 ’Release-iphonesimulator’ 폴더에 저장 됨.

3. Xcode 메뉴에서 Project Seettings… 창을 열면 아래와 같이 빌드 디렉토리 경로를 볼 수 있다.

 

4. 또는 Xcode 의 Project Navigator 에서 Products에 빌드된 파일로 빌드된 디렉토리를 확인할 수 있다.

5. 위 4번 파일을 이용하여 빌드된 디렉토리로 이동하면 다음과 같다.

6. 빌드된 라이브러리 파일을 Device, Simulator에 따라 파일이름을 각각 ‘libXXXD.a’, ‘libXXXS.a’로 바꿔 Desktop에 복사한다.

7. 콘솔창을 띄워 Desktop폴더로 이동

cd ~/Desktop

8. 콘솔창에서 lipo명령을 통해 Device와 Simulator 로 빌드된 두 라이브러리를 합친다. 

lipo -create ./libXXXD.a ./libXXXS.a -output ./libXXX.a

9. 8번에서 생성된 Fat 라이브러리 Architectures 를 확인 하도록 한다.
lipo -I libXXX.a

10. 9 결과가 Device 아키텍쳐(armv7, arm64, armv7s) Simulator 아키텍쳐(i386, x86_64)
포함되었다면 정상이므로 ‘libXXX.a’ 배포하도록 한다.

 

 

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (2/2)

2020/12/10 - [iOS/Tips] - Fat Static Library 빌드 (1/2)

2020/12/10 - [iOS/Tips] - Custom UserAgent 설정

2020/12/10 - [iOS/Tips] - CocoaPods 설치 및 제거

2020/12/10 - [iOS/Tips] - Clang diagnostic 경고 무시하기

2020/12/10 - [개발노트] - Bluetooth UUID

2020/12/08 - [개발노트] - 모바일 앱 메모리덤프 이슈 해결방법

2020/12/08 - [프로그래밍/Java Script] - Android, iOS 앱 설치여부 체크 및 스토어 이동

2020/08/21 - [Android/Tips] - aab파일 apk파일로 변환

2020/08/11 - [iOS/Swift] - WKWebView 화면 출력 완료 이벤트

2020/08/06 - [iOS/Tips] - 개발관련 폴더 경로

2020/07/19 - [Android/Tips] - 안드로이드 원격 디버깅 방법

2020/07/18 - [Android/Tips] - Cannot convert string value 'JETPACK_COMPOSE' to an enum value of type 'com.android.builder.model.AndroidGradlePluginProjectFlags$BooleanFlag' (valid case insensitive values: APPLICATION_R_CLASS_CONSTANT_IDS, TEST_R_CLASS_CONSTANT_IDS, TRANSITIVE_R_CLASS)

2020/07/18 - [Android/Tips] - OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended

2020/07/17 - [iOS/Tips] - 웹에서 iOS 앱 설치여부 체크

반응형

'개발 > iOS' 카테고리의 다른 글

웹뷰에서 javascript 함수 동기식 호출  (0) 2020.12.10
Fat Static Library 빌드 (2/2)  (0) 2020.12.10
Custom UserAgent 설정  (0) 2020.12.10
CocoaPods 설치 및 제거  (0) 2020.12.10
Clang diagnostic 경고 무시하기  (0) 2020.12.10
블로그 이미지

SKY STORY

,

Custom UserAgent 설정

개발/iOS 2020. 12. 10. 15:21
반응형
//--------------------------------------------------------
/// WKWebView (type 1 - Objective C)
WKWebView *wkWebView = [[WKWebView alloc] initWithFrame:CGRectZero];
[wkWebView loadHTMLString:@"<html></html>" baseURL:nil];
[wkWebView evaluateJavaScript:@"navigator.appName" completionHandler:^(id __nullable appName, NSError * __nullable error) {
    NSLog(@"%@", appName);
}];

[wkWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id __nullable userAgent, NSError * __nullable error) {
    NSLog(@"%@", userAgent);
    // iOS 8.3
    // Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12F70
    // iOS 9.0
    // Mozilla/5.0 (iPhone; CPU iPhone OS 9_0 like Mac OS X) AppleWebKit/601.1.32 (KHTML, like Gecko) Mobile/13A4254v
    // Custom UserAgent
    NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
    NSString *newUserAgent = [NSString stringWithFormat:@"%@ %@", userAgent, appName];
    if (@available(iOS 9.0, *)) {
        wkWebView.customUserAgent = newUserAgent;
    } else {
        NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:newUserAgent, @"UserAgent", nil];
        [[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];
    }
}];

//--------------------------------------------------------
/// WKWebView (type 2 - Objective C)
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.applicationNameForUserAgent = @"My Custom Useragent Name";
WKWebView *wkWebView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
NSLog(@"%@", wkWebView.configuration.applicationNameForUserAgent); // My Custom Useragent Name
NSLog(@"%@", wkWebView.customUserAgent); // null
[wkWebView loadHTMLString:@"<html></html>" baseURL:nil];
[wkWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id __nullable userAgent, NSError * __nullable error) {
    NSLog(@"%@", userAgent);
    // iOS 9
    // Mozilla/5.0 (iPhone; CPU iPhone OS 9_0 like Mac OS X) AppleWebKit/601.1.32 (KHTML, like Gecko) My Custom Useragent Name
}];

//--------------------------------------------------------
/// WKWebView (type 1 - Swift) Available: iOS 9+
wkWebView.evaluateJavaScript("navigator.userAgent") {
    [weak webView] (result, error) in
if let webView = webView, let userAgent = result as? String {
    webView.customUserAgent = userAgent + "/Custom Agent"
} }

//--------------------------------------------------------
/// WKWebView (type 1 - Swift) Available: iOS 9+
let webConfiguration = WKWebViewConfiguration()
let webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.customUserAgent = "ExampleApp/1.0 (iPhone)"

//--------------------------------------------------------
/// WKWebView (type 2 - Swift) Available: iOS 9+
/// Append to the default User Agent
let webConfiguration = WKWebViewConfiguration()
webConfiguration.applicationNameForUserAgent = "ExampleApp/1.0 (iPhone)"
let webView = WKWebView(frame: .zero, configuration: webConfiguration)
// Mozilla/5.0 (iPhone; CPU iPhone OS 11_2 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) ExampleApp/1.0 (iPhone)
 
//--------------------------------------------------------
/// UIWebView (Objective C)
UIWebView *webView = [[UIWebView alloc] init];
[webView loadHTMLString:@"<html></html>" baseURL:nil];
NSString *appName = [webView stringByEvaluatingJavaScriptFromString:@"navigator.appName"];
NSLog(@"%@", appName);
NSString *userAgent = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
NSLog(@"%@", userAgent);
// iOS 8.3
// Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12F70
// iOS 9.0
// Mozilla/5.0 (iPhone; CPU iPhone OS 9_0 like Mac OS X) AppleWebKit/601.1.32 (KHTML, like Gecko) Mobile/13A4254v}

// Custom UserAgent
NSString *newUserAgent = [NSString stringWithFormat:@"%@ %@", userAgent, appName];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:newUserAgent, @"UserAgent", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];

//--------------------------------------------------------
/// UIWebView (Swift) Available: iOS 9+
webView.customUserAgent = (UIWebView().stringByEvaluatingJavaScript(from: "navigator.userAgent") ?? "") + "/Custom agent"



//--------------------------------------------------------
//--------------------------------------------------------
/// Example :

// UIWebView
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectZero];
NSString *userAgent = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
NSString *newUserAgent = [NSString stringWithFormat:@"%@ %@", userAgent, appName];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:newUserAgent, @"UserAgent", nil]; [[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];

// WKWebView
WKWebView *wkWebView = [[WKWebView alloc]initWithFrame:CGRectZero];
[wkWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id userAgent, NSError *error) {
    NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
    NSString *newUserAgent = [NSString stringWithFormat:@"%@ %@", userAgent, appName];
    if (@available(iOS 9.0, *)) {
        wkWebView.customUserAgent = newUserAgent;
    } else {
        NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:newUserAgent, @"UserAgent", nil];
        [[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];
    }
}];

 

2020/12/10 - [iOS/Tips] - Custom UserAgent 설정

2020/12/10 - [iOS/Tips] - CocoaPods 설치 및 제거

2020/12/10 - [iOS/Tips] - Clang diagnostic 경고 무시하기

2020/12/10 - [개발노트] - Bluetooth UUID

2020/12/08 - [개발노트] - 모바일 앱 메모리덤프 이슈 해결방법

2020/12/08 - [프로그래밍/Java Script] - Android, iOS 앱 설치여부 체크 및 스토어 이동

2020/08/21 - [Android/Tips] - aab파일 apk파일로 변환

2020/08/11 - [iOS/Swift] - WKWebView 화면 출력 완료 이벤트

2020/08/06 - [iOS/Tips] - 개발관련 폴더 경로

2020/07/19 - [Android/Tips] - 안드로이드 원격 디버깅 방법

2020/07/18 - [Android/Tips] - Cannot convert string value 'JETPACK_COMPOSE' to an enum value of type 'com.android.builder.model.AndroidGradlePluginProjectFlags$BooleanFlag' (valid case insensitive values: APPLICATION_R_CLASS_CONSTANT_IDS, TEST_R_CLASS_CONSTANT_IDS, TRANSITIVE_R_CLASS)

2020/07/18 - [Android/Tips] - OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended

2020/07/17 - [iOS/Tips] - 웹에서 iOS 앱 설치여부 체크

2020/07/14 - [Android/Tips] - 웹에서 안드로이드 앱을 실행 (Custom URL Scheme)

2020/07/11 - [OS/Mac OS X] - SMC(System Management Controller) 재설정

반응형

'개발 > iOS' 카테고리의 다른 글

Fat Static Library 빌드 (2/2)  (0) 2020.12.10
Fat Static Library 빌드 (1/2)  (1) 2020.12.10
CocoaPods 설치 및 제거  (0) 2020.12.10
Clang diagnostic 경고 무시하기  (0) 2020.12.10
WKWebView 화면 출력 완료 이벤트  (0) 2020.08.11
블로그 이미지

SKY STORY

,