ARC-隐式桥接 [英] ARC - implicit bridging
问题描述
如果我理解正确,我们可以将 void * 归类为"C可保留指针类型". 因此,将其分配给Objective-C对象将被隐式桥接.但是,编译器会引发错误,要求进行显式桥接.
const void * somePtr = (void *)0x12345678;
- (void)someMethod:(id)sender
{
NSObject *obj = (NSObject *)somePtr;
}
此外,我检查了空指针常量,并且在编译时没有显式桥接.
NSObject *obj = (void *)0;
我正在使用XCode 4.5(Clang 4.1(标签/Apple/clang-421.11.66)(基于 LLVM 3.1svn )).
问题: 我知道为NSObject分配一些任意/不相关的指针有点奇怪,但是我想确保是否正确理解了规则.我对"C可保留指针类型" 有点怀疑.尤其是关于(可能合格)和(可能合格)的意图.我们可以将哪些指针类型归类为"C可保留指针类型" ?
还有,它实际上是指系统全局变量" 语句中来自系统的全局变量吗?
3.3.2.转换为具有已知语义的可保留对象指针类型 [从Apple 4.0开始,LLVM 3.1]
如果表达式是与保留无关的已知,则该表达式是
:
- Objective-C字符串文字,
- 来自const系统全局变量 C可保留指针类型的加载,
- 或空指针常量.
如果强制转换操作数是未知保留的或未知不可保留的,则将转换视为__bridge强制转换.
7.8. C种可保留的指针类型
如果类型是指向(可能是限定词) void的指针,或者是指向(可能是限定词)结构或类类型的指针,则它是C可保留的指针类型.
http://clang.llvm.org/docs/AutomaticReferenceCounting.html
似乎const系统全局变量实际上不需要显式桥接. 即kCFBooleanTrue(CFBoolean实例),kCFNumberNaN或kABPersonPhoneMobileLabel.
NSObject *obj = (NSObject *)kCFBooleanTrue;
请注意,CFBoolean不是免费的桥接器,但编译器仍可以隐式桥接它. 我定义了全局常量,但无法使用隐式桥接对其进行编译. 因此,我想知道编译器如何确定变量是否来自系统? (或者可能正在检查类型是否来自CoreFoundation.framework,这不是一个很好的解决方案...)
---编辑---
参考rob mayoff的答案,我尝试了隐式桥接,但是它仍然没有用.可能有一个编译器标志,用于将该文件确定为Core Foundation文件.
NSObject *obj = (NSObject *)myGlobal;
"mytest.h"文件
#ifndef mytest_h
#define mytest_h
#pragma clang arc_cf_code_audited begin
typedef const struct MyStruct * MyStructPtr;
CF_EXPORT
const MyStructPtr myGlobal;
#pragma clang arc_cf_code_audited end
#endif
"mytest.c"文件
#include "mytest.h"
struct MyStruct {
int a;
};
static struct MyStruct __myglobal = { 123 };
const MyStructPtr myGlobal = &__myglobal;
---编辑---
我还修改了CoreFoundation.framework中的CFNumber.h头文件,并删除了 CF_IMPLICIT_BRIDGING_ENABLED/CF_IMPLICIT_BRIDGING_DISABLED ,然后清理/构建了该项目,但并未禁用这些常量的隐式桥接. >
If i understood correctly we could classify void * as a "C retainable pointer type". So, assigning it to an Objective-C object will be implicitly bridged. However, compiler raises error that explicit bridging is required.
const void * somePtr = (void *)0x12345678;
- (void)someMethod:(id)sender
{
NSObject *obj = (NSObject *)somePtr;
}
Also, i checked the null pointer constant and it compiles without explicit bridging.
NSObject *obj = (void *)0;
I am using XCode 4.5(Clang 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)).
Question: I know it's a little bit weird to assign some arbitrary/irrelevant pointer to NSObject but i want to make sure if am correctly understanding the rules. I am little bit suspicious about the "C retainable pointer type". description; especially about the intention of (possibly qualified) and (possibly qualifier). What pointer types could we classify as "C retainable pointer type"?
Also, does it actually mean a global variable from system by the "system global variable" statement?
3.3.2. Conversion to retainable object pointer type of expressions with known semantics [beginning Apple 4.0, LLVM 3.1]
An expression is known retain-agnostic if it is:
- an Objective-C string literal,
- a load from a const system global variable of C retainable pointer type,
- or a null pointer constant.
If the cast operand is known unretained or known retain-agnostic, the conversion is treated as a __bridge cast.
7.8. C retainable pointer types
A type is a C retainable pointer type if it is a pointer to (possibly qualified) void or a pointer to a (possibly qualifier) struct or class type.
http://clang.llvm.org/docs/AutomaticReferenceCounting.html
It seems that const system global variables actually do not require explicit bridging. i.e. kCFBooleanTrue(CFBoolean instance), kCFNumberNaN or kABPersonPhoneMobileLabel.
NSObject *obj = (NSObject *)kCFBooleanTrue;
Note that CFBoolean is not toll free bridged but it could be still implicitly bridged by compiler. I define global constants but could not get them compiled with implicit bridging. So, i wonder how could compiler determine if a variable comes from system or not? (Or may be it is checking if type comes from CoreFoundation.framework which is not a neat solution...)
--- EDIT ---
Referring to rob mayoff's answer, i tried implicit bridging but it still did not work. May be there is a compiler flag to determine the file as a Core Foundation file.
NSObject *obj = (NSObject *)myGlobal;
"mytest.h" File
#ifndef mytest_h
#define mytest_h
#pragma clang arc_cf_code_audited begin
typedef const struct MyStruct * MyStructPtr;
CF_EXPORT
const MyStructPtr myGlobal;
#pragma clang arc_cf_code_audited end
#endif
"mytest.c" File
#include "mytest.h"
struct MyStruct {
int a;
};
static struct MyStruct __myglobal = { 123 };
const MyStructPtr myGlobal = &__myglobal;
--- EDIT ---
I also modified the CFNumber.h header file in CoreFoundation.framework and removed CF_IMPLICIT_BRIDGING_ENABLED/CF_IMPLICIT_BRIDGING_DISABLED, then clean/build the project and yet it did not disable implicit bridging for those constants.
这篇关于ARC-隐式桥接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!