64 位模式下的 objc_setAssociatedObject 函数错误,而不是 32 位模式 [英] objc_setAssociatedObject function error in 64bit mode not in 32bit

查看:22
本文介绍了64 位模式下的 objc_setAssociatedObject 函数错误,而不是 32 位模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的项目中使用了一个名为 SKSTableView 的整洁的表格视图控制器,它允许每个表格行有多个子行.此代码在 32 位 模式下完美运行,但是当我在 iPhone 5S 或模拟器中以 4 英寸 64 位模式运行它时,当您点击一行以获取子行时,它会崩溃.我对 64 位和 32 位 iOS 系统的差异一无所知.我很想了解这里发生了什么.

I am using a neat table view controller called SKSTableView in my project which allows each table row to have a number of sub rows. This code works perfectly in 32bit mode but when I run it on my iPhone 5S or in the Simulator in 4-inch 64bit mode, when you tap on a row to get the sub rows it crashes. I do not have any knowledge of the differences of 64bit and 32bit iOS systems. I would love to understand what it happening here.

您会注意到 *SubRowObjectKey 设置为 void - 我得到的错误是:EXC_BAD_ACCESS_(代码=EXC_I386_GPFLT)
尝试访问不存在的东西(?)

You will notice that the *SubRowObjectKey is set to void- the error I get is: EXC_BAD_ACCESS_(code=EXC_I386_GPFLT)
Which is a general protection fault trying to access something that is not there(?)

当它崩溃时 Xcode 突出显示这行代码:
objc_setAssociatedObject(self, SubRowObjectKey, subRowObj, OBJC_ASSOCIATION_ASSIGN);

When it crashes Xcode highlights this line of code:
objc_setAssociatedObject(self, SubRowObjectKey, subRowObj, OBJC_ASSOCIATION_ASSIGN);

还有这个:*(subRowObj) 的打印说明:(id) [0] =SubRowObjectKey 的打印说明:

Also there is this: Printing description of *(subRowObj): (id) [0] = Printing description of SubRowObjectKey:

它似乎在 32 位模式下运行良好,但在 64 位模式下似乎有些松散.下面是我正在查看的代码部分.

It seems to be working great in 32bit mode but some how in 64bit it seems to loose where it is. Here below is the section of the code I am looking at.

#pragma mark - NSIndexPath (SKSTableView)
static void *SubRowObjectKey;
@implementation NSIndexPath (SKSTableView)
@dynamic subRow;
- (NSInteger)subRow
{
    id subRowObj = objc_getAssociatedObject(self, SubRowObjectKey);
    return [subRowObj integerValue];
}
- (void)setSubRow:(NSInteger)subRow
{
    if (IsEmpty(@(subRow))) {
        return;
    }
    id subRowObj = @(subRow);
    objc_setAssociatedObject(self, SubRowObjectKey, subRowObj, OBJC_ASSOCIATION_ASSIGN);
}
+ (NSIndexPath *)indexPathForSubRow:(NSInteger)subrow inRow:(NSInteger)row inSection:(NSInteger)section
{
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
    indexPath.subRow = subrow;   
    return indexPath;
}

您可以在此处下载并使用代码:https://github.com/sakkaras/SKSTableView

You can download and play with the code here: https://github.com/sakkaras/SKSTableView

推荐答案

objc_setAssociatedObject() 似乎不适用于标记指针".标记指针是特殊的指针,它不指向,而是指向值"存储在指针本身的(某些位)中.例如,请参见 Objective-C 中的标记指针,其中包含指向更多信息的链接.

It seems that objc_setAssociatedObject() does not work with "tagged pointers". Tagged pointers are special pointers that do not point to something, but the "value" is stored in (some bits of) the pointer itself. See for example Tagged pointers in Objective-C, which has links to more information.

标记指针仅用于 64 位代码,例如对于索引路径小行号和节号,或小号对象.

Tagged pointers are used with 64-bit code only, e.g. for index paths with small row and section numbers, or small number objects.

很容易验证在标记指针上设置关联对象会因 EXC_BAD_ACCESS 崩溃在 iOS 7/64 位上:

It can easily be verified that setting an associated object on a tagged pointer crashes with EXC_BAD_ACCESS on iOS 7/64-bit:

static void *key = &key;

id obj = [NSIndexPath indexPathForRow:1 inSection:1];
objc_setAssociatedObject(obj, key, @"345", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
// --> EXC_BAD_ACCESS_(code=EXC_I386_GPFLT) 

同样的事情发生在

id obj = @1;
id obj = [NSDate dateWithTimeIntervalSinceReferenceDate:0];

它们也是 64 位模式下的标记指针.

which are also tagged pointers in 64-bit mode.

我找不到有关此限制的任何文档,因此将其视为iOS中的错误.这里报告了类似的问题:https://github.com/EmbeddedSources/iAsync/issues/22.我认为这值得一个错误向 Apple 报告.

I could not find any documentation of this restriction and would consider this a bug in iOS. A similar problem was reported here: https://github.com/EmbeddedSources/iAsync/issues/22. I think this is worth a bug report to Apple.

(备注:该问题在 OS X/64 位上不会出现.)

(Remark: The problem does not occur on OS X/64-bit.)

更新(可能的解决方案/变通方法):SKSTableView"项目(问题末尾的链接)在NSIndexPath 和关联对象将第三个属性子行"添加到索引路径.这个子行临时设置在

Update (possible solution/workaround): The "SKSTableView" project (link at the end of the question) uses a category on NSIndexPath and associated objects to add a third property "subrow" to an index path. This subrow is set temporarily in

tableView:cellForRowAtIndexPath:

of SKSTableView 将当前子行传递给

of SKSTableView to pass the current subrow to the

tableView:cellForSubRowAtIndexPath:indexPath

ViewController 类中的委托方法.

如果您改用适当的"三级索引路径,则不需要关联对象,示例应用程序也以 64 位模式运行.

If you use "proper" three-level index paths instead, the associated object is not needed and the sample app runs in 64-bit mode as well.

我对示例项目进行了以下更改:

I made the following changes to the sample project:

SKSTableView.m 中:

+ (NSIndexPath *)indexPathForSubRow:(NSInteger)subrow inRow:(NSInteger)row inSection:(NSInteger)section
{
    // Change:
    //NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
    //indexPath.subRow = subrow;
    // To:
    NSUInteger indexes[] = { section, row, subrow };
    NSIndexPath *indexPath = [NSIndexPath indexPathWithIndexes:indexes length:3];

    return indexPath;
}

属性访问器方法

- (NSInteger)subRow;
- (void)setSubRow:(NSInteger)subRow;

不再需要.

ViewController.m 中:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForSubRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"UITableViewCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (!cell)
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

    // Change:
    //cell.textLabel.text = [NSString stringWithFormat:@"%@", self.contents[indexPath.section][indexPath.row][indexPath.subRow]];
    // To:
    cell.textLabel.text = [NSString stringWithFormat:@"%@", self.contents[[indexPath indexAtPosition:0]][[indexPath indexAtPosition:1]][[indexPath indexAtPosition:2]]];

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    return cell;
}

这篇关于64 位模式下的 objc_setAssociatedObject 函数错误,而不是 32 位模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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