objective-c - NSInvocation 傻瓜?

NSInvocation 究竟是如何工作的?有好的介绍吗?

我在理解以下代码(来自 Cocoa Programming for Mac OS X,第 3 版)的工作原理方面特别有问题,但我也能够独立于教程示例应用这些概念。代码:

- (void)insertObject:(Person *)p inEmployeesAtIndex:(int)index
{
    NSLog(@"adding %@ to %@", p, employees);
    // Add inverse of this operation to undo stack
    NSUndoManager *undo = [self undoManager];
    [[undo prepareWithInvocationTarget:self] removeObjectFromEmployeesAtIndex:index];
    if (![undo isUndoing])
        [undo setActionName:@"Insert Person"];

    // Finally, add person to the array
    [employees insertObject:p atIndex:index];
}

- (void)removeObjectFromEmployeesAtIndex:(int)index
{
    Person *p = [employees objectAtIndex:index];
    NSLog(@"removing %@ from %@", p, employees);
    // Add inverse of this operation to undo stack
    NSUndoManager *undo = [self undoManager];
    [[undo prepareWithInvocationTarget:self] insertObject:p
                                       inEmployeesAtIndex:index];
    if (![undo isUndoing])
        [undo setActionName:@"Delete Person"];

    // Finally, remove person from array
    [employees removeObjectAtIndex:index];
}

我明白它想要做什么。 (顺便说一句,employees 是自定义 Person 类的 NSArray。)

作为 .NET 人员,我尝试将不熟悉的 Obj-C 和 Cocoa 概念与大致类似的 .NET 概念联系起来。这是否类似于 .NET 的委托(delegate)概念,但没有类型?

这不是从书中 100% 清楚的,所以我正在寻找真正的 Cocoa/Obj-C 专家的补充内容,目的是让我理解简单 (-ish) 示例背后的基本概念。我真的希望能够独立应用这些知识——直到第 9 章,我都没有遇到任何困难。但是现在……

提前致谢!

最佳答案

根据Apple's NSInvocation class reference :

An NSInvocation is an Objective-C message rendered static, that is, it is an action turned into an object.

还有,一点更详细:

消息的概念是 Objective-C 哲学的核心。任何时候你调用一个方法,或者访问某个对象的一个​​变量,你就是在向它发送一条消息。 NSInvocation 当您想在不同的时间点向对象发送消息或多次发送相同的消息时会派上用场。 NSInvocation 允许你描述你将要发送的消息,然后调用它(实际上是发送到目标对象)。


例如,假设您想将字符串添加到数组中。您通常会按如下方式发送 addObject: 消息:

[myArray addObject:myString];

现在,假设您想使用 NSInvocation 在其他时间点发送此消息:

首先,您将准备一个 NSInvocation 对象以与 NSMutableArrayaddObject: 选择器一起使用:

NSMethodSignature * mySignature = [NSMutableArray
    instanceMethodSignatureForSelector:@selector(addObject:)];
NSInvocation * myInvocation = [NSInvocation
    invocationWithMethodSignature:mySignature];

接下来,您将指定将消息发送到哪个对象:

[myInvocation setTarget:myArray];

指定您希望发送给该对象的消息:

[myInvocation setSelector:@selector(addObject:)];

并为该方法填写任何参数:

[myInvocation setArgument:&myString atIndex:2];

请注意,对象参数必须通过指针传递。感谢 Ryan McCuaig指出这一点,请参阅 Apple's documentation了解更多详情。

此时,myInvocation是一个完整的对象,描述了一个可以发送的消息。要实际发送消息,您会调用:

[myInvocation invoke];

这最后一步将导致消息被发送,本质上是执行 [myArray addObject:myString];.

把它想象成发送电子邮件。您打开一个新电子邮件(NSInvocation 对象),填写您要发送给的人(对象)的地址,为收件人输入一条消息(指定一个 selector 和参数),然后点击“发送”(调用 invoke)。

见 Using NSInvocation了解更多信息。 见 Using NSInvocation如果上述方法不起作用。


NSUndoManager 使用 NSInvocation 对象,以便它可以反转 命令。本质上,您所做的是创建一个 NSInvocation 对象来表示:“嘿,如果您想撤消我刚刚所做的事情,请将此消息发送到该对象,并带有这些参数”。您将 NSInvocation 对象提供给 NSUndoManager,然后它将该对象添加到可撤消操作的数组中。如果用户调用“Undo”,NSUndoManager 只需在数组中查找最近的操作,并调用存储的 NSInvocation 对象来执行必要的操作。

见 Registering Undo Operations了解更多详情。

https://stackoverflow.com/questions/313400/

相关文章:

objective-c - 为什么在 C 中将 1,000,000,000 写为 1000*1000

ios - iPhone SDK : what is the difference between

ios - 如何设置一个简单的委托(delegate)来在两个 View Controller 之间

objective-c - Swift References 中的 _ 下划线代表什么?

ios - 无法同时满足约束,将尝试通过打破约束来恢复

ios - UIView 隐藏/显示动画

objective-c - "FOUNDATION_EXPORT"与 "extern"

ios - 以编程方式在 UIStackView 中添加 View

ios - 如何在 UITableView 中设置分隔符的全宽

iphone - 从实例中获取类的名称