2012-02-27 36 views
13

Tôi cần viết lib trong ứng dụng iOS của mình.Làm cách nào để biết trình biên dịch có hỗ trợ ARC được bật không?

Tuyên bố nên trước quá trình xác định như sau:

myObject ... 

#if ARC 
    // do nothing 
#else 
    [myObject release] 
#endif 

hoặc thời gian chạy quá trình như:

if (ARC) { 
    // do nothing 
} else { 
    [myObject release]; 
} 

Làm thế nào tôi có thể làm gì?

Xin hãy giúp tôi! Cảm ơn bạn.

+0

@Sulthan, có các trường hợp sử dụng hợp lý cho đối tượng địa lý. Giống như việc đảm bảo người dùng thư viện của bạn không chỉ lấy các nguồn hỗ trợ ARC của bạn và biên dịch chúng mà không cần hỗ trợ ARC, rò rỉ bộ nhớ khắp nơi (đã xảy ra với tôi cách đây vài ngày). Điều đó nói rằng, mẫu mã được đưa ra trong câu hỏi trông thực sự lộn xộn. – zoul

+1

@zoul Bạn không bao giờ có thể chuẩn bị cho mọi thứ mà người dùng có thể làm. Trong trường hợp của bạn, một xác nhận đơn giản nếu ARC được bật là đủ.Cố gắng để có mã tương thích với cả ARC và MRC phải kết thúc bằng một mã rất phức tạp (hoặc lộn xộn), với khả năng đọc kém. Và mã không thể đọc được là khó khăn để duy trì. – Sulthan

+0

Đồng ý, khẳng định là những gì tôi có trong tâm trí. – zoul

Trả lời

28

Bạn có thể sử dụng __has_feature, như vậy:

#if __has_feature(objc_arc) 
// ARC is On 
#else 
// ARC is Off 
#endif 

Nếu bạn cũng muốn xây dựng với GCC (của Apple GCC không hỗ trợ ARC), bạn cũng có thể cần những điều sau đây để xác định trình biên dịch:

#if defined(__clang) 
// It's Clang 
#else 
// It's GCC 
#endif 

cập nhật

kết hợp, họ sẽ mang hình thức chung:

#if defined(__clang)  

#if !defined(__has_feature) 
// idk when clang introduced this 
#error This version of clang does not support __has_feature 
#endif 

#define MON_IS_ARC_ENABLED_IN_THIS_TRANSLATION __has_feature(objc_arc) 

#else 
// for every compiler other than clang: 

#if defined(__has_feature) 
#error Another compiler supports __has_feature 
#endif 

#define MON_IS_ARC_ENABLED_IN_THIS_TRANSLATION 0 

#endif 

Sau đó chỉ cần sử dụng MON_IS_ARC_ENABLED_IN_THIS_TRANSLATION trong nguồn của bạn hoặc để biết thêm #define s.

Nếu trình biên dịch bạn sử dụng thêm hỗ trợ, bạn sẽ phải thêm trường hợp cho điều đó (và lỗi trình biên dịch có khả năng sẽ gặp lỗi trong trường hợp này, vì nó có khả năng cấm sử dụng số lần truy cập).

Lưu ý rằng điều này có kiểm tra bổ sung để chứng minh cách người ta có thể (và nên) tránh xác định số nhận dạng dành riêng (dựa trên cuộc trò chuyện trong nhận xét). Nó không đầy đủ, nhưng là một cuộc biểu tình. Nếu bạn thấy mình viết có điều kiện __has_feature kiểm tra thường xuyên, bạn có thể muốn xác định macro mới để làm giảm và đơn giản hóa các định nghĩa.

+0

Đừng kiểm tra danh tính trình biên dịch, kiểm tra tính tương thích. Sử dụng [#ifdef __has_feature] (http://clang.llvm.org/docs/LanguageExtensions.html#__has_feature_extension) như được khuyến nghị bởi clang. – Jesper

+0

cảm ơn sự hỗ trợ của bạn! –

+0

@ Jesper Tôi xem xét đề nghị của clang là một sai lầm. a) Nó có thể thất bại (khá dễ dàng). b) Bạn không nên khai báo rằng được dành riêng cho trình biên dịch và/hoặc thực hiện - cụ thể là, từ liên kết của bạn: '#define __has_feature (x) 0 // Khả năng tương thích với trình biên dịch không clang.' – justin

2

Bạn thường không muốn làm những việc như thế này:

#if ARC 
    // do nothing 
#else 
    [myObject release] 
#endif 

Bởi vì đó là một công thức cho thảm họa, có nhiều lỗi vi tế ẩn trong mã như vậy. Nhưng nếu bạn có một trường hợp sử dụng lành mạnh cho điều đó, bạn sẽ có lẽ được tốt hơn off với một macro (Tôi không biết __has_feature, nhờ Justin!):

#if __has_feature(objc_arc) 
    #define MY_RELEASE(x) while (0) {} 
#else 
    #define MY_RELEASE(x) [x release] 
#endif 

Nhưng tôi sẽ rất lo lắng khi sử dụng ngay cả này, tiềm năng đau là rất lớn :)

+0

cảm ơn sự hỗ trợ của bạn! –

9

Bạn có thể làm điều đó sử dụng các macro:

#if !defined(__clang__) || __clang_major__ < 3 
    #ifndef __bridge 
     #define __bridge 
    #endif 

    #ifndef __bridge_retain 
     #define __bridge_retain 
    #endif 

    #ifndef __bridge_retained 
     #define __bridge_retained 
    #endif 

    #ifndef __autoreleasing 
     #define __autoreleasing 
    #endif 

    #ifndef __strong 
     #define __strong 
    #endif 

    #ifndef __unsafe_unretained 
     #define __unsafe_unretained 
    #endif 

    #ifndef __weak 
     #define __weak 
    #endif 
#endif 

#if __has_feature(objc_arc) 
    #define SAFE_ARC_PROP_RETAIN strong 
    #define SAFE_ARC_RETAIN(x) (x) 
    #define SAFE_ARC_RELEASE(x) 
    #define SAFE_ARC_AUTORELEASE(x) (x) 
    #define SAFE_ARC_BLOCK_COPY(x) (x) 
    #define SAFE_ARC_BLOCK_RELEASE(x) 
    #define SAFE_ARC_SUPER_DEALLOC() 
    #define SAFE_ARC_AUTORELEASE_POOL_START() @autoreleasepool { 
    #define SAFE_ARC_AUTORELEASE_POOL_END() } 
#else 
    #define SAFE_ARC_PROP_RETAIN retain 
    #define SAFE_ARC_RETAIN(x) ([(x) retain]) 
    #define SAFE_ARC_RELEASE(x) ([(x) release]) 
    #define SAFE_ARC_AUTORELEASE(x) ([(x) autorelease]) 
    #define SAFE_ARC_BLOCK_COPY(x) (Block_copy(x)) 
    #define SAFE_ARC_BLOCK_RELEASE(x) (Block_release(x)) 
    #define SAFE_ARC_SUPER_DEALLOC() ([super dealloc]) 
    #define SAFE_ARC_AUTORELEASE_POOL_START() NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    #define SAFE_ARC_AUTORELEASE_POOL_END() [pool release]; 
#endif 

trên đây đến từ trang web: http://raptureinvenice.com/arc-support-without-branches/; nhưng tôi đã dán nó để đảm bảo nó không bị mất.

Các vấn đề liên quan