如何将参数列表应用于 Objective C 中的块?

发布于 2024-12-09 20:42:23 字数 186 浏览 0 评论 0原文

Objective C 是否有类似 Smalltalk 的 Block valueWithArguments 的功能?

我正在寻找一个具有如下签名的函数:

apply(^(), NSArray* args)

或者,有没有办法通过参数列表调用选择器?

Does Objective C have a function like Smalltalk's Block valueWithArguments?

I'm looking for a function with a signature like:

apply(^(), NSArray* args)

Alternatively, is there a way to call a selector over a list of arguments?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

擦肩而过的背影 2024-12-16 20:42:23

对于块,您可能需要执行一些 va_args 魔法。可以使用可变参数调用选择器,但您可能需要一些帮助器来减轻痛苦。

NSObject+performSelectorWithArgsArray.h

@interface NSObject (performSelectorWithArgsArray)
- (id)performSelector:(SEL)sel withArgsArray:(NSArray *)args;
@end

NSObject+performSelectorWithArgsArray.m

@implementation NSObject (performSelectorWithArgsArray)
- (id)performSelector:(SEL)sel withArgsArray:(NSArray *)args {
  NSInvocation *inv = [NSInvocation invocationWithMethodSignature:
                       [self methodSignatureForSelector:sel]];
  [inv setSelector:sel];
  [inv setTarget:self];
  for (int i = 0; i < args.count; i++) {
    id a = [args objectAtIndex:i];
    [inv setArgument:&a atIndex:2 + i]; // 0 is target, 1 is cmd-selector
  }
  [inv invoke];

  NSNumber *r;
  [inv getReturnValue:&r];
  return r;
}
@end

然后像这样使用它:

#import "NSObject+performSelectorWithArgs.h"

@interface SomeClass : NSObject
@end

@implementation SomeClass
- (NSNumber *)withA:(NSNumber *)a withB:(NSNumber *)b {
  return [NSNumber numberWithInt:a.intValue + b.intValue];
}
@end

- (void)someMethod {
  SomeClass *a = [[SomeClass alloc] init];
  SEL sel = @selector(withA:withB:);
  NSArray *args = [NSArray arrayWithObjects:
                   [NSNumber numberWithInt:2],
                   [NSNumber numberWithInt:3],
                   nil];
  NSNumber *r = [a performSelector:sel withArgsArray:args];
  NSLog(@"%d", r.intValue);
}

如果你选择做这样的事情,我建议你真正阅读一下 NSInitation 的工作原理,因为它会非常困难。不确定是否可以在不要求所有参数和返回值都是对象的情况下执行此操作。

With blocks you probably have to do some va_args magic. Calling a selector with variable arguments can be done but you probably want some helpers to make it a bit less painful.

NSObject+performSelectorWithArgsArray.h

@interface NSObject (performSelectorWithArgsArray)
- (id)performSelector:(SEL)sel withArgsArray:(NSArray *)args;
@end

NSObject+performSelectorWithArgsArray.m

@implementation NSObject (performSelectorWithArgsArray)
- (id)performSelector:(SEL)sel withArgsArray:(NSArray *)args {
  NSInvocation *inv = [NSInvocation invocationWithMethodSignature:
                       [self methodSignatureForSelector:sel]];
  [inv setSelector:sel];
  [inv setTarget:self];
  for (int i = 0; i < args.count; i++) {
    id a = [args objectAtIndex:i];
    [inv setArgument:&a atIndex:2 + i]; // 0 is target, 1 is cmd-selector
  }
  [inv invoke];

  NSNumber *r;
  [inv getReturnValue:&r];
  return r;
}
@end

And then use it like this:

#import "NSObject+performSelectorWithArgs.h"

@interface SomeClass : NSObject
@end

@implementation SomeClass
- (NSNumber *)withA:(NSNumber *)a withB:(NSNumber *)b {
  return [NSNumber numberWithInt:a.intValue + b.intValue];
}
@end

- (void)someMethod {
  SomeClass *a = [[SomeClass alloc] init];
  SEL sel = @selector(withA:withB:);
  NSArray *args = [NSArray arrayWithObjects:
                   [NSNumber numberWithInt:2],
                   [NSNumber numberWithInt:3],
                   nil];
  NSNumber *r = [a performSelector:sel withArgsArray:args];
  NSLog(@"%d", r.intValue);
}

If you choose to do something like this I recommend that you really read up on how NSInvocation works as it can bite quite hard. Not sure if it is possible to do this without requiring that all arguments and return value are objects.

空名 2024-12-16 20:42:23

NSArray 具有方法 enumerateObjectsUsingBlock:enumerateObjectsWithOptions:usingBlock: 是您正在寻找的吗?

[[NSArray arrayWithObjects:@"a", @"b", @"c", nil]
 enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  NSLog(@"%d: %@", idx, obj);
}];

NSArray has the methods enumerateObjectsUsingBlock: and enumerateObjectsWithOptions:usingBlock: is that what you are looking for?

[[NSArray arrayWithObjects:@"a", @"b", @"c", nil]
 enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  NSLog(@"%d: %@", idx, obj);
}];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文