ARC-隐式桥接 [英] ARC - implicit bridging

查看:130
本文介绍了ARC-隐式桥接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我理解正确,我们可以将 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆