정적 라이브러리의 Objective-C 범주


153

정적 라이브러리를 iPhone 프로젝트에 올바르게 연결하는 방법을 알려주십시오. 앱 프로젝트에 추가 된 정적 라이브러리 프로젝트를 직접 종속성 (대상-> 일반-> 직접 종속성)으로 사용하고 모두 정상적으로 작동하지만 카테고리는 작동합니다. 정적 라이브러리에 정의 된 카테고리가 앱에서 작동하지 않습니다.

그래서 내 질문은 일부 프로젝트의 정적 라이브러리를 다른 프로젝트에 추가하는 방법입니다.

그리고 일반적으로 다른 프로젝트의 앱 프로젝트 코드에서 사용하는 가장 좋은 방법은 무엇입니까?


1
글쎄, 일부 답변을 발견 하고이 질문에 이미 답변이 된 것 같습니다 (죄송합니다. stackoverflow.com/questions/932856/… )
Vladimir

답변:


228

해결 방법 : Xcode 4.2부터는 라이브러리 자체가 아닌 라이브러리와 연결되는 응용 프로그램으로 이동하여 프로젝트 네비게이터에서 프로젝트를 클릭하고 앱의 대상을 클릭 한 다음 설정을 빌드하고 "기타"를 검색하면됩니다. 링커 플래그 "에서 + 버튼을 클릭하고 '-ObjC'를 추가하십시오. '-all_load'및 '-force_load'는 더 이상 필요하지 않습니다.

세부 정보 : 다양한 포럼, 블로그 및 Apple 문서에서 일부 답변을 찾았습니다. 이제 검색 및 실험에 대한 간단한 요약을 시도합니다.

(Apple Technical Q & A QA1490 https://developer.apple.com/library/content/qa/qa1490/_index.html 인용)에 의한 문제 :

Objective-C는 각 함수 (또는 Objective-C의 메소드)에 대해 링커 심볼을 정의하지 않습니다. 대신 링커 심볼이 각 클래스에 대해서만 생성됩니다. 기존 클래스를 범주로 확장하는 경우 링커는 핵심 클래스 구현의 개체 코드와 범주 구현을 연결하는 것을 모릅니다. 이렇게하면 결과 응용 프로그램에서 생성 된 개체가 범주에 정의 된 선택기에 응답하지 않습니다.

그리고 그들의 해결책 :

이 문제를 해결하려면 정적 라이브러리가 -ObjC 옵션을 링커에 전달해야합니다. 이 플래그는 링커가 라이브러리에서 Objective-C 클래스 또는 카테고리를 정의하는 모든 오브젝트 파일을로드하게합니다. 이 옵션은 일반적으로 응용 프로그램에로드 된 추가 객체 코드로 인해 더 큰 실행 파일을 생성하지만 기존 클래스의 범주를 포함하는 효과적인 Objective-C 정적 라이브러리를 성공적으로 만들 수 있습니다.

iPhone 개발 FAQ에도 권장 사항이 있습니다.

정적 라이브러리의 모든 Objective-C 클래스를 어떻게 연결합니까? Other Linker Flags 빌드 설정을 -ObjC로 설정하십시오.

및 플래그 설명 :

- all_load의 하중을 정적 아카이브 라이브러리의 모든 구성원.

- ObjC 로드에게 오브젝티브 C 클래스 또는 카테고리를 구현하는 정적 아카이브 라이브러리의 모든 구성원.

- force_load (path_to_archive) 로드 지정된 정적 아카이브 라이브러리의 모든 구성원. 참고 : -all_load는 모든 아카이브의 모든 멤버를 강제로로드합니다. 이 옵션을 사용하면 특정 아카이브를 대상으로 지정할 수 있습니다.

* force_load를 사용하여 앱 이진 크기를 줄이고 all_load가 어떤 경우에 발생할 수있는 충돌을 피할 수 있습니다.

예, 프로젝트에 추가 된 * .a 파일과 함께 작동합니다. 그러나 직접 의존으로 추가 된 lib 프로젝트에 문제가있었습니다. 그러나 나중에 내 잘못이라는 것을 알았습니다. 직접 종속성 프로젝트가 제대로 추가되지 않았을 수 있습니다. 제거하고 단계를 다시 추가하면 :

  1. 앱 프로젝트에서 lib 프로젝트 파일을 드래그 앤 드롭하거나 Project-> Add to project…로 추가하십시오.
  2. lib project icon-mylib.a 파일 이름에서 화살표를 클릭하고이 mylib.a 파일을 끌어서 Target-> Link Binary With Library 그룹에 놓으십시오.
  3. 첫 페이지에서 대상 정보를 열고 (일반) 종속성 목록에 내 라이브러리를 추가하십시오.

그 후 모든 것이 정상적으로 작동합니다. 내 경우에는 "-ObjC"플래그로 충분했습니다.

또한 http://iphonedevelopmentexperiences.blogspot.com/2010/03/categories-in-static-library.html 블로그의 아이디어에 관심이있었습니다 . 저자는 -all_load 또는 -ObjC 플래그를 설정하지 않고 lib의 카테고리를 사용할 수 있다고 말합니다. 그는 링커가이 파일을 사용하도록하기 위해 빈 hummy 클래스 인터페이스 / 구현을 카테고리 h / m 파일에 추가합니다. 그리고 그렇습니다.이 트릭은 일을합니다.

그러나 저자는 심지어 더미 객체를 인스턴스화하지조차 않았다고 말했다. 음… 찾은대로 카테고리 파일에서 "실제"코드를 명시 적으로 호출해야합니다. 따라서 적어도 클래스 함수를 호출해야합니다. 그리고 우리는 심지어 더미 수업이 필요하지 않습니다. 단일 c 함수도 마찬가지입니다.

따라서 lib 파일을 다음과 같이 작성하면

// mylib.h
void useMyLib();

@interface NSObject (Logger)
-(void)logSelf;
@end


// mylib.m
void useMyLib(){
    NSLog(@"do nothing, just for make mylib linked");
}


@implementation NSObject (Logger)
-(void)logSelf{
    NSLog(@"self is:%@", [self description]);
}
@end

우리가 useMyLib ()를 호출하면; App 프로젝트의 어느 곳에서나 어느 클래스에서나 logSelf 카테고리 메소드를 사용할 수 있습니다.

[self logSelf];

테마에 대한 더 많은 블로그 :

http://t-machine.org/index.php/2009/10/13/how-to-make-an-iphone-static-library-part-1/

http://blog.costan.us/2009/12/fat-iphone-static-libraries-device-and.html


8
Apple 기술 노트는 "이 문제를 해결하려면 정적 라이브러리에 대한 대상 링크가 -ObjC 옵션을 링커에 전달해야합니다."라고 수정되었습니다. 이것은 위에서 인용 한 것과 반대입니다. 라이브러리 자체가 아닌 앱을 연결할 때 포함해야 함을 확인했습니다.
Ken Aspeslagh

doc developer.apple.com/library/mac/#qa/qa1490/_index.html 에 따르면 -all_load 또는 -force_load 플래그를 사용해야합니다. 언급했듯이 링커에는 64 비트 Mac App 및 iPhone App에 버그가 있습니다. "중요 : 64 비트 및 iPhone OS 응용 프로그램의 경우 -ObjC가 범주 만 포함하고 클래스가없는 정적 라이브러리에서 객체 파일을로드하지 못하게하는 링커 버그가 있습니다. 해결 방법은 -all_load 또는 -force_load 플래그를 사용하는 것입니다."
Robin

2
@ Ken Aspelagh : 감사합니다. 같은 문제가있었습니다. -ObjC 및 -all_load 플래그 는 라이브러리가 아닌 앱 자체에 추가해야합니다 .
titaniumdecoy

3
이 질문을 처음 접하는 사람들은 이제 그것이 구식임을 주목해야합니다. tonklon의 답변을 확인하십시오 stackoverflow.com/a/9224606/322748 (all_load / force_load는 더 이상 필요하지 않습니다)
Jay Peyer

나는 거의 30 분 동안이 일에 갇혀 있었고 시행 착오로 방금 만들었습니다. 어쨌든 감사합니다. 이 답변은 +1의 가치가 있습니다.
Deepukjayan 2016 년

118

Vladimir의 답변은 실제로 꽤 좋지만 여기서 더 많은 배경 지식을주고 싶습니다. 언젠가 누군가가 내 답장을 찾아서 도움이 될 수도 있습니다.

컴파일러는 소스 파일 (.c, .cc, .cpp, .m)을 객체 파일 (.o)로 변환합니다. 소스 파일 당 하나의 오브젝트 파일이 있습니다. 객체 파일에는 심볼, 코드 및 데이터가 포함됩니다. 운영 체제에서 오브젝트 파일을 직접 사용할 수 없습니다.

이제 동적 라이브러리 (.dylib), 프레임 워크,로드 가능한 번들 (.bundle) 또는 실행 가능한 바이너리를 빌드 할 때 이러한 오브젝트 파일은 링커에 의해 서로 연결되어 운영 체제가 "사용 가능한"것으로 간주하는 것을 생성합니다. 특정 메모리 주소로 직접로드합니다.

그러나 정적 라이브러리를 빌드 할 때 이러한 모든 오브젝트 파일은 단순히 큰 아카이브 파일에 추가되므로 정적 라이브러리의 확장자 (아카이브의 경우 .a)입니다. 따라서 .a 파일은 객체 (.o) 파일의 아카이브 일뿐입니다. 압축하지 않은 TAR 아카이브 또는 ZIP 아카이브를 생각하십시오. 단일 .a 파일을 전체 .o 파일보다 쉽게 ​​복사 할 수 있습니다 (자바와 유사하게 배포하기 위해 .class 파일을 .jar 아카이브로 압축하는 Java와 유사).

바이너리를 정적 라이브러리 (= 아카이브)에 링크 할 때 링커는 아카이브에있는 모든 심볼의 테이블을 가져와 바이너리가 참조하는 심볼을 확인합니다. 링커가 참조 심볼을 포함하는 오브젝트 파일 만 실제로로드하며 링크 프로세스에서 고려합니다. 예를 들어, 아카이브에 50 개의 객체 파일이 있지만 바이너리에만 사용되는 심볼이 20 개만 포함 된 링커는 20 개만로드하고 나머지 30 개는 링크 프로세스에서 완전히 무시합니다.

이 언어는 컴파일 타임에 가능한 한 많은 작업을 시도하기 때문에 C 및 C ++ 코드에 매우 효과적입니다 (C ++에는 런타임 전용 기능이 있지만). 그러나 Obj-C는 다른 종류의 언어입니다. Obj-C는 런타임 기능에 크게 의존하며 많은 Obj-C 기능은 실제로 런타임 전용 기능입니다. Obj-C 클래스는 실제로 C 함수 또는 전역 C 변수 (적어도 현재 Obj-C 런타임에서)와 비교할 수있는 기호를 가지고 있습니다. 링커는 클래스의 참조 여부를 확인할 수 있으므로 사용중인 클래스를 결정할 수 있습니다. 정적 라이브러리에있는 객체 파일의 클래스를 사용하는 경우 링커에서 심볼이 사용중인 것으로 보이기 때문에이 객체 파일은 링커에 의해로드됩니다. 범주는 런타임 전용 기능이며 범주는 클래스 또는 함수와 같은 기호가 아니며 링커에서 범주의 사용 여부를 확인할 수 없습니다.

링커에서 Obj-C 코드가 포함 된 객체 파일을로드하면 모든 Obj-C 부분은 항상 연결 단계의 일부입니다. 따라서 범주를 포함하는 객체 파일이로드되면 해당 기호가 "사용 중"(클래스, 함수, 전역 변수 일 수 있음)으로 간주되어 범주가로드되어 런타임에 사용할 수있게됩니다. . 그러나 오브젝트 파일 자체가로드되지 않으면 런타임에 오브젝트 파일의 카테고리를 사용할 수 없습니다. 카테고리 포함 된 객체 파일 은 결코 그것을 포함하지 않기 때문에로드되지 에는 문자 링커는 것이 지금까지 "사용"생각을. 그리고 이것은 전체 문제입니다.

몇 가지 솔루션이 제안되었으며 이제이 모든 기능이 어떻게 작동하는지 알았으므로 제안 된 솔루션에 대해 다시 살펴 보겠습니다.

  1. 한 가지 해결책은 -all_load링커 호출 에 추가 하는 것입니다. 링커 플래그는 실제로 무엇을합니까? 실제로는 링커에 다음과 같이 알려줍니다. " 사용중인 심볼이 있는지 여부에 관계없이 모든 아카이브의 모든 객체 파일을로드합니다 . '물론 작동하지만 큰 바이너리를 생성 할 수도 있습니다.

  2. 다른 해결책은 -force_load아카이브 경로를 포함하여 링커 호출 에 추가 하는 것입니다. 이 플래그는와 정확히 동일 -all_load하지만 지정된 아카이브에 대해서만 작동합니다 . 물론 이것은 잘 작동합니다.

  3. 가장 인기있는 솔루션은 -ObjC 링커 호출 하는 것입니다. 링커 플래그는 실제로 무엇을합니까? 이 플래그는 링커에 " Obj-C 코드가 포함되어있는 경우 모든 아카이브에서 모든 오브젝트 파일로드 "를 지시합니다 . "모든 Obj-C 코드"에는 범주가 포함됩니다. 이것은 잘 작동하며 Obj-C 코드가 포함되지 않은 객체 파일을 강제로로드하지 않습니다 (이것은 여전히 ​​요청시로드됩니다).

  4. 또 다른 해결책은 다소 새로운 Xcode 빌드 설정 Perform Single-Object Prelink입니다. 이 설정은 무엇을합니까? 사용 가능한 경우 모든 오브젝트 파일 (소스 파일 당 하나 있음)이 단일 오브젝트 파일로 병합됩니다 (실제 링크되지 않으므로 이름 PreLink )과이 단일 오브젝트 파일 (때로는 "마스터 오브젝트"라고도 함 파일 ")이 보관함에 추가됩니다. 이제 마스터 오브젝트 파일의 기호가 사용중인 것으로 간주되면 전체 마스터 오브젝트 파일이 사용중인 것으로 간주되므로 모든 Objective-C 부분이 항상로드됩니다. 클래스는 일반적인 기호이므로 이러한 정적 라이브러리의 단일 클래스를 사용하여 모든 범주를 가져 오는 것으로 충분합니다.

  5. 마지막 해결책은 블라디미르가 그의 대답의 끝에 추가 한 트릭입니다. 카테고리 만 선언하는 소스 파일에 " 가짜 기호 "를 넣으십시오 . 런타임에 범주 중 하나를 사용하려면 컴파일 타임에 가짜 기호 를 참조해야합니다. 이렇게하면 링커에 의해 오브젝트 파일이로드되므로 모든 Obj-C 코드가로드됩니다. 예를 들어 빈 함수 본문이있는 함수이거나 (호출 될 때 아무것도하지 않을 것입니다) 전역 변수에 액세스 할 수 있습니다 (예 : 전역 변수)int한번 읽거나 쓴 후에는 이것으로 충분합니다). 위의 다른 모든 솔루션과 달리이 솔루션은 런타임에 사용 가능한 카테고리에 대한 제어를 컴파일 된 코드로 전환합니다 (링크 및 사용 가능하게하려면 심볼에 액세스합니다. 그렇지 않으면 심볼에 액세스하지 않고 링커는 무시 함). 그것).

그게 다야

아, 잠깐, 한 가지 더 있습니다 :
링커에는이라는 옵션이 -dead_strip있습니다. 이 옵션은 무엇을합니까? 링커에서 객체 파일을로드하기로 결정한 경우, 객체 파일의 모든 심볼은 사용 여부에 관계없이 연결된 바이너리의 일부가됩니다. 예를 들어 객체 파일에는 100 개의 함수가 포함되어 있지만 이진은이 중 하나만 사용합니다. 객체 파일은 전체적으로 추가되거나 전혀 추가되지 않기 때문에 100 개의 모든 기능이 바이너리에 계속 추가됩니다. 링커에서는 일반적으로 오브젝트 파일을 부분적으로 추가 할 수 없습니다.

그러나 링커에 "데드 스트립"을 지시하면 링커는 먼저 모든 객체 파일을 이진 파일에 추가하고 모든 참조를 확인한 다음 마지막으로 이진 파일에서 사용하지 않는 심볼을 검색합니다. 사용하다). 사용하지 않는 것으로 확인 된 모든 기호는 최적화 단계의 일부로 제거됩니다. 위의 예에서 99 개의 사용하지 않는 기능이 다시 제거되었습니다. 이 같은 옵션을 사용하는 경우 매우 유용합니다 -load_all, -force_load또는 Perform Single-Object Prelink이러한 옵션은 쉽게 어떤 경우에 극적 이진 크기를 날려 버릴 수 있기 때문에 죽은 스트립은 다시 사용하지 않는 코드와 데이터를 제거합니다.

데드 스트리핑은 C 코드에서 매우 잘 작동합니다 (예 : 사용하지 않는 함수, 변수 및 상수는 예상대로 제거됨). 또한 C ++에서도 매우 잘 작동합니다 (예 : 사용하지 않는 클래스는 제거됨). 완벽하지는 않지만 일부 경우 심볼을 제거해도 괜찮지 만 일부 언어는 이러한 언어에 적합합니다.

Obj-C는 어떻습니까? 잊어 버리세요! Obj-C의 데드 스트립은 없습니다. Obj-C는 런타임 기능 언어이므로 컴파일러는 컴파일 타임에 심볼의 실제 사용 여부를 말할 수 없습니다. 예를 들어 직접 참조하는 코드가 없으면 Obj-C 클래스를 사용하고 있지 않습니까? 잘못된! 클래스 이름이 포함 된 문자열을 동적으로 작성하고 해당 이름에 대한 클래스 포인터를 요청하고 클래스를 동적으로 할당 할 수 있습니다. 예를 들어

MyCoolClass * mcc = [[MyCoolClass alloc] init];

나는 또한 쓸 수 있었다

NSString * cname = @"CoolClass";
NSString * cnameFull = [NSString stringWithFormat:@"My%@", cname];
Class mmcClass = NSClassFromString(cnameFull);
id mmc = [[mmcClass alloc] init];

두 경우 모두 mmc"MyCoolClass"클래스의 객체에 대한 참조이지만 두 번째 코드 샘플에서이 클래스에 대한 직접적인 참조없습니다 (정적 문자열 인 클래스 이름조차 포함하지 않음). 모든 것은 런타임에만 발생합니다. 그리고 비록 클래스 실제로 실제 심볼 이더라도 마찬가지 입니다. 범주는 실제 기호가 아니기 때문에 범주의 경우 더 나쁩니다.

따라서 수백 개의 객체가있는 정적 라이브러리가 있지만 대부분의 바이너리에는 그 중 몇 개만 필요하면 위의 솔루션 (1) ~ (4)를 사용하지 않는 것이 좋습니다. 그렇지 않으면 대부분의 클래스가 사용되지 않더라도 이러한 모든 클래스를 포함하는 매우 큰 바이너리로 끝납니다. 클래스에는 실제 기호가 있고 클래스를 직접 참조하는 한 (두 번째 코드 샘플이 아닌) 링커는 사용법을 잘 식별하므로 클래스에는 일반적으로 특별한 솔루션이 필요하지 않습니다. 그러나 범주의 경우 실제로 필요한 범주 만 포함 할 수 있으므로 솔루션 (5)를 고려하십시오.

예를 들어 NSData에 대한 카테고리를 원한다면 (예 : 압축 / 압축 해제 방법 추가) 헤더 파일을 생성합니다 :

// NSData+Compress.h
@interface NSData (Compression)
    - (NSData *)compressedData;
    - (NSData *)decompressedData;
@end

void import_NSData_Compression ( );

구현 파일

// NSData+Compress
@implementation NSData (Compression)
    - (NSData *)compressedData 
    {
        // ... magic ...
    }

    - (NSData *)decompressedData
    {
        // ... magic ...
    }
@end

void import_NSData_Compression ( ) { }

이제 코드의 아무 곳이나 import_NSData_Compression()호출해야합니다. 어디에서 호출되는지 또는 얼마나 자주 호출되는지는 중요하지 않습니다. 실제로 실제로 호출 할 필요는 없습니다. 링커가 그렇게 생각하면 충분합니다. 예를 들어 프로젝트의 어느 곳에 나 다음 코드를 넣을 수 있습니다.

__attribute__((used)) static void importCategories ()
{
    import_NSData_Compression();
    // add more import calls here
}

importCategories()코드를 호출 할 필요가 없습니다.이 속성은 컴파일러와 링커가 그것이 호출되지 않은 경우에도 호출되었다고 믿게합니다.

마지막 팁 : 최종 링크 호출에
추가 -whyload하면 링커는 사용중인 심볼로 인해 라이브러리에서로드 한 오브젝트 파일을 빌드 로그에 인쇄합니다. 사용중인 것으로 간주되는 첫 번째 심볼 만 인쇄하지만 반드시 해당 오브젝트 파일을 사용하는 유일한 심볼은 아닙니다.


1
-whyload링커가 무언가를하고있는 이유를 디버그하려고 시도하는 것은 매우 감사합니다 .
벤 S

에 옵션 Dead Code StrippingBuild Settings>Linking있습니다. -dead_strip추가 한 것과 동일 Other Linker Flags합니까?
Xiao

1
@Sean 예, 동일합니다. 모든 빌드 설정에 존재하는 "빠른 도움말"을 읽으십시오. 그 대답은 바로 다음과 같습니다 : postimg.org/image/n7megftnr/full
Mecki

@Mecki 감사합니다. 나는 제거하려고 노력했다 -ObjC. 그래서 나는 당신의 핵을 시도했지만 그것은 불평한다 "import_NSString_jsonObject()", referenced from: importCategories() in main.o ld: symbol(s) not found. 나는 import_NSString_jsonObject임베디드 프레임 워크에라는 이름을 넣고 내 끝에 with 문을 Utility추가 합니다. #import <Utility/Utility.h>__attribute__AppDelegate.h
Xiao

@Sean 링커에서 심볼을 찾을 수 없으면 심볼이 포함 된 정적 라이브러리에 대해 링크하지 않은 것입니다. 프레임 워크에서 ah 파일을 가져 오는 것만으로는 Xcode가 프레임 워크와 연결되지 않습니다. 프레임 워크는 프레임 워크 빌드 단계와의 링크에서 명시 적으로 링크되어야합니다. 연결 문제에 대한 자체 질문을 열고 의견에 답하는 것은 번거롭고 빌드 로그 출력과 같은 정보를 제공 할 수도 없습니다.
Mecki

24

이 문제는 LLVM 에서 수정되었습니다 . 수정 프로그램은 LLVM 2.9의 일부로 제공됩니다. 수정 프로그램을 포함하는 첫 번째 Xcode 버전은 LLVM 3.0과 함께 제공되는 Xcode 4.2입니다. 의 사용 -all_load또는이 -force_load엑스 코드 4.2은 작업을 할 때 더 이상 필요하지 않습니다 -ObjC 여전히 필요하다.


이거 확실하니? Xcode 4.3.2를 사용하여 LLVM 3.1로 컴파일하는 iOS 프로젝트를 작업 중이며 여전히 문제입니다.
Ashley Mills

알았어, 조금 정확하지 않았다. -ObjC플래그는 여전히 필요하며 항상있을 것입니다. 해결 방법은 -all_load또는 의 사용법이었습니다 -force_load. 그리고 그것은 더 이상 필요하지 않습니다. 위의 답변을 수정했습니다.
tonklon

불필요하더라도 -all_load 플래그를 포함시키는 데 단점이 있습니까? 어떤 식 으로든 컴파일 / 시작 시간에 영향을 줍니까?
ZS

Xcode 버전 4.5 (4G182)로 작업 중이며 -ObjC 플래그가 Objective C 런타임의 깊이와 같은 모양으로 사용하려는 타사 종속성에서 인식 할 수없는 선택기 오류를 이동합니다. "-[__ NSArrayM map :] : 인식 할 수없는 선택기가 인스턴스로 전송되었습니다 ... ". 단서가 있습니까?
Robert Atkins

16

정적 라이브러리를 컴파일 할 때이 문제를 완전히 해결하려면 다음을 수행하십시오.

Xcode 빌드 설정으로 이동하여 단일 오브젝트 사전 링크 수행을 예로 설정하거나 GENERATE_MASTER_OBJECT_FILE = YES빌드 구성 파일에서 설정하십시오.

기본적으로 링커는 각 .m 파일에 대해 .o 파일을 생성합니다. 따라서 카테고리는 다른 .o 파일을 얻습니다. 링커는 정적 라이브러리 .o 파일을 볼 때 클래스 당 모든 심볼의 인덱스를 생성하지 않습니다 (런타임은 중요하지 않음).

이 지시문은 링커에게 모든 객체를 하나의 큰 .o 파일로 묶으라고 요청하며,이를 통해 정적 라이브러리를 처리하는 링커가 모든 클래스 범주의 색인을 얻도록합니다.

그것을 명확히 희망하십시오.


연결 대상에 -ObjC를 추가하지 않고도 문제가 해결되었습니다.
Matthew Crenshaw

최신 버전의 BlocksKit 라이브러리로 업데이트 한 후이 설정을 사용하여 문제를 해결해야했습니다 (이미 -ObjC 플래그를 사용하고 있었지만 여전히 문제가 있음).
rakmoh

1
실제로 당신의 대답은 옳지 않습니다. 나는 "같은 클래스의 모든 카테고리를 하나의 .o 파일로 묶을 링커를 요청하지 않는다"고 정적 라이브러리를 만들기 전에 링커가 모든 객체 파일 (.o)을 하나의 큰 객체 파일로 링크하도록 요청한다 그들 / 그것. 라이브러리에서 심볼을 참조하면 모든 심볼이로드됩니다. 그러나 심볼이 참조되지 않으면 (예 : 라이브러리에 카테고리 만있는 경우 작동하지 않는 경우) 작동하지 않습니다.
Mecki

NSData와 같은 기존 클래스에 범주를 추가하면 이것이 효과가 있다고 생각하지 않습니다.
밥 화이트 맨

기존 클래스에 카테고리를 추가하는 데 문제가 있습니다. 플러그인이 런타임에 인식 할 수 없습니다.
David Dunham

9

정적 라이브러리 링크 논의가 올 때마다 언급되지 않는 한 가지 요소 는 카테고리 자체를 빌드 단계-> 복사 파일에 포함시키고 정적 라이브러리 자체의 소스를 컴파일해야 한다는 사실입니다 .

애플은 최근 에 iOS에서 정적 라이브러리 사용하기에서도이 사실을 강조하지 않습니다 .

나는 하루 종일 -objC와 -all_load 등의 모든 종류의 변형을 시도했지만 아무것도 나오지 못했습니다. 질문은 그 문제를 주목했습니다. (나를 잘못하지 마라. 당신은 여전히 ​​-objC 일을해야하지만 .. 그 이상입니다.)

또한 항상 저에게 도움이 된 또 다른 작업은 항상 포함 된 정적 라이브러리를 항상 자체적으로 빌드한다는 것입니다. 그런 다음 엔 클로징 응용 프로그램을 빌드합니다.


-1

정적 라이브러리의 "public"헤더에 카테고리가 있어야합니다. #import "MyStaticLib.h"

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.