作为方法参数,int或NSInteger作为对象。Objective-C

14

我在传递一个数字作为方法参数时遇到了一些问题:

- (void)meth2:(int)next_int;

而要调用该方法,我需要这样做:

int next_int = 1;
[self performSelectorOnMainThread:@selector(meth2:) withObject:next_int waitUntilDone:NO];
//update next_int and call meth2 again
在这一点上,我得到了一个“从整数转换为指针时没有进行强制转换”的错误,并且使用 NSInteger 也会发生同样的情况。 NSNumber 不太有用,因为它是不可变的,而我需要不断更改值。有什么想法如何解决这个问题吗?谢谢。

我认为AnthonyF的回答是唯一正确的答案,不需要改变方法的参数类型。 - DawnSong
4个回答

23

如果你只是想调用该方法,你可以使用标准语法:

[self meth2:next_int];

如果您确实需要使用performSelectorOnMainThread:,您可以将数字包装在一个NSNumber中进行调用。您说您不能这样做是因为您需要更改数字,但您只需提取一个int并更改该int即可:

[self performSelectorOnMainThread:@selector(meth2:) withObject:[NSNumber numberWithInt:next_int] waitUntilDone:NO];
// ... later ...
- (void)meth2:(NSNumber *)number {
  int myInt = [number intValue];
  // do stuff with myInt
}

但也许你的意思是希望从对 meth2 的调用中获取数字的值作为输出。 如果这是你的意思,那么你可以传递一个双指针,这样你就可以接收到一个新的对象:

- (void)meth2:(NSNumber **)number {
  int myInt = [*number intValue];
  // do stuff with myInt
  *number = [NSNumber numberWithInt:myInt];
}
// The caller can now operate like this:
NSNumber *number = [NSNumber numberWithInt:next_int];
[self performSelectorOnMainThread:@selector(meth2:) withObject:&number waitUntilDone:YES];
int returnInt = [*number intValue];
当然,那并不是真正的线程安全,所以如果你正在使用多个线程进行操作,我建议使用@synchronized关键字来访问多线程访问的变量,或者设置原子属性(即未声明为nonatomic的属性)。此外,冰毒对你有害!!哈哈

嗨,泰勒,我不确定@synchronized关键字,我会去了解一下,但由于这个整数变量被用作线程的“输出”,所以不需要担心并发等问题。 ..withObject:[NSNumber numberWithInt:next_int]..很好用,但(NSNumber **)给了我一个不兼容的指针类型警告。 我会记住关于meth的事情...谢谢! - sergiobuj

6

在传递之前,将整数包装在NSNumber中:

int next_int = 1
NSNumber *theNumber = [NSNumber numberWithInt:next_int];
[self performSelectorOnMainThread:@selector(meth2:) withObject:theNumber waitUntilDone:NO];

那么,您的-meth2:方法可能看起来像这样:
- (void)meth2:(NSNumber*)theNumber
{
    int next_int = [theNumber intValue];
    // do whatever
}

4
这个方法有点取巧,但在 ARC 下可以运行:
int next_int = 1;
[self performSelectorOnMainThread:@selector(meth2:) 
                       withObject:(__bridge id)(void*)next_int 
                    waitUntilDone:NO];
__bridge关键字告诉编译器在ARC下忽略引用计数,但它需要一个指针,所以你需要先将int强制转换为C风格的void指针。当你的方法接收到该消息时,它会把那个对象指针视为整数。
注意:如果你可以改变方法以接受NSNumber而不是整数,那么这将是“正确”的修复方法。不幸的是,这并不总是可能的。

如果您想传递枚举(例如在设置枚举属性时),这是一个不错的技巧;例如 [cell performSelector:@selector(setSortOrder:) withObject:(__bridge id)(void*)order]; - tiritea
我补充你的答案 https://stackoverflow.com/a/62445156/1107242 - DawnSong

2

由于next_int不是一个对象,因此您无法将其用作withObject:的参数。

请更改您的调用方式:

[self performSelectorOnMainThread:@selector(meth2:) 
      withObject:[NSNumber numberWithInt:next_int] waitUntilDone:NO];

编辑: 将meth2更改为接受NSNumber而不是int


1
这将导致运行时崩溃,因为您还需要修改方法签名以接受 NSNumber - Shaggy Frog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接