以下代码按预期工作:
NSLog(@"%@", [NSString stringWithString:@"test"]; // Logs "test"
Run Code Online (Sandbox Code Playgroud)
但当我用一个替换它时NSInvocation,我得到一个完全不同的结果:
Class class = [NSString class];
SEL selector = @selector(stringWithString:);
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
[class methodSignatureForSelector:selector]];
[invocation setTarget:class];
[invocation setSelector:selector];
[invocation setArgument:@"test" atIndex:2];
[invocation invoke];
id returnValue = nil;
[invocation getReturnValue:&returnValue];
NSLog(@"%@", returnValue); // Logs "NSCFString"
Run Code Online (Sandbox Code Playgroud)
我搜索过高低,但无法弄清楚这一点.有帮助吗?谢谢!
在释放NSInvocation时是否释放保留的参数,还是需要手动对NSInvocation的参数列表中的对象进行释放?
在上下文中要求以下两个问题来维护NSOperationQueue和NSInvocationOperation.
由于我使用此概念下载多个视频,如何在完成下载视频后从NSOperationQueue中删除/释放添加的NSInvocationOperation?
而且,如果我想在下载过程中停止下载特定视频,我该怎么办?
我尝试将CGRect传递给NSInvocation(setArgument:atIndex :).我用NSValue包装它,推送到NSArry,然后从NSArray获取并使用NSValue(getValue :).调用(getValue :)方法会导致更改前声明的索引NSInteger i.任何人都可以说为什么会这样?
NSString className = @"UIButton";
Class cls = NSClassFromString(className);
cls pushButton5 = [[cls alloc] init];
CGRect rect =CGRectMake(20,220,280,30);
NSMethodSignature *msignature1;
NSInvocation *anInvocation1;
msignature1 = [pushButton5 methodSignatureForSelector:@selector(setFrame:)];
anInvocation1 = [NSInvocation invocationWithMethodSignature:msignature1];
[anInvocation1 setTarget:pushButton5];
[anInvocation1 setSelector:@selector(setFrame:)];
NSValue* rectValue = [NSValue valueWithCGRect:rect];
NSArray *params1;
params1= [NSArray arrayWithObjects:rectValue,nil];
id currentVal = [params1 objectAtIndex:0];
NSInteger i=2;
if ([currentVal isKindOfClass:[NSValue class]]) {
void *bufferForValue;
[currentVal getValue:&bufferForValue];
[anInvocation1 setArgument:&bufferForValue atIndex:i];
}else {
[anInvocation1 setArgument:¤tVal atIndex:i];
}
[anInvocation1 invoke];
Run Code Online (Sandbox Code Playgroud)
当这个(getValue:)方法实现'i'的值从2更改为类似的东西:1130102784,并且(setArgument:atIndex:)我有一个SIGABRT因为索引i超出界限. …
我在库中有一个看起来像这样的方法:
- (id)initWithSomeObjects:(NSString *)something, ... NS_REQUIRES_NIL_TERMINATION;
Run Code Online (Sandbox Code Playgroud)
我真的想用数组而不是var args来调用它,因为我想传入的对象数量是可以改变的.
有没有办法,使用performSelector或NSInvocation或objc_msgSend或其他什么,我可以调用var args方法,参数来自数组?
当我将NSInvocation的返回值设置为NSString时,调用者正在接收NSCFString.
在我的情况下,我嘲笑从单元测试包含的文件中拉出一个包路径:
[[[_bundlePartial stub] andDo:^(NSInvocation *invocation) {
NSString* resourceName = [invocation getArgumentAtIndexAsObject:2];
NSString* type = [invocation getArgumentAtIndexAsObject:3];
NSString* path = [[NSBundle bundleForClass:self.class] pathForResource:resourceName ofType:type];
if (!path)
{
path = [_bundleOriginal pathForResource:resourceName ofType:type];
}
[invocation setReturnValue:(void*)path];
}] pathForResource:OCMOCK_ANY ofType:OCMOCK_ANY];
Run Code Online (Sandbox Code Playgroud)
我称之为:
NSString* jsonPathInBundle = [[NSBundle mainBundle] pathForResource:self.fileName ofType:self.fileExtension];
Run Code Online (Sandbox Code Playgroud)
不幸的是我回来了NSCFString.这是有道理的,因为我的NSString由NSCFString支持,但是当我丢失桥时,我不能再在对象上调用NSString实例方法.有没有办法可以将值作为NSString返回?
我正在尝试调用一个带有多个(2+)参数的选择器(可以确定参数的数量).但是,选择器在编译时是未知的(实际上是使用NSSelectorFromString生成的).
在Objective-C中,我可以创建一个调用并为其设置参数并调用它.但这在Swift中不可用.有没有办法解决?喜欢:
let obj = SomeClass()
let selector = NSSelectorFromString("arg1:arg2:arg3:") //selector, arguments known only at runtime
//invoke selector
Run Code Online (Sandbox Code Playgroud) 我想在主线程上执行动画(导致UIKit对象不是线程安全的),但是在一些单独的线程中准备它.我有(baAnimation - 之前已经分配了CABasicAnimation):
SEL animationSelector = @selector(addAnimation:forKey:);
NSString *keyString = @"someViewAnimation";
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[workView.layer methodSignatureForSelector:animationSelector]];
[inv setTarget:workView.layer];
[inv setSelector:animationSelector];
[inv setArgument:baAnimation atIndex:2];
[inv setArgument:keyString atIndex:3];
[inv performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:NO];
Run Code Online (Sandbox Code Playgroud)
我明白了:
***+ [NSCFString length]:无法识别的选择器发送到类0x1fb36a0
呼叫:
> #0 0x020984e6 in objc_exception_throw
> #1 0x01f7e8fb in +[NSObject doesNotRecognizeSelector:]
> #2 0x01f15676 in ___forwarding___
> #3 0x01ef16c2 in __forwarding_prep_0___
> #4 0x01bb3c21 in -[CALayer addAnimation:forKey:]
> #5 0x01ef172d in __invoking___
> #6 0x01ef1618 in -[NSInvocation invoke]
Run Code Online (Sandbox Code Playgroud)
但[workView.layer addAnimation:baAnimation forKey:@"someViewAnimation"];工作正常.我究竟做错了什么?
我正在寻找一种在主线程上使用两个参数执行选择器的好方法
我真的很喜欢用
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
Run Code Online (Sandbox Code Playgroud)
方法,除了现在我有两个参数.
所以基本上我有一个委托,我需要在加载图像时通知:
[delegate imageWasLoaded:(UIImage *)image fromURL:(NSString *)URLString;
Run Code Online (Sandbox Code Playgroud)
但是我可以在后台线程中调用我执行此操作的方法,并且委托将使用此图像来更新UI,因此需要在主线程中完成.所以我真的希望代理在主线程中得到通知.
所以我看到一个选项 - 我可以创建一个字典,这样我只有一个对象,它包含两个我需要传递的参数.
NSDictionary *imageData = [NSDictionary dictionaryWithObjectsAndKeys:image, @"image", URLString, @"URLstring", nil];
[(NSObject *)delegate performSelectorOnMainThread:@selector(imageWasLoaded:) withObject: imageData waitUntilDone:NO];
Run Code Online (Sandbox Code Playgroud)
但这种方法对我来说似乎不对.有没有更优雅的方式来做到这一点?也许使用NSInvocation?提前致谢.
我试图从回调块内推出一个视图控制器.我想要推送的视图控制器包含一个UIWebView,它抱怨我应该在主线程上调用它.我尝试使用NSInvocation无济于事.我presentModalViewController:animated该如何调用主线程?
[vc requestUserPermissionWithCallback:^(BOOL inGranted)
{
if (inGranted)
{
if (serviceType == PXServiceTypeTwitter)
{
//[ad.rootViewController presentModalViewController:vc animated: YES]; // crashes
NSInvocation *invocation = [NSInvocation invocationWithTarget:ad.rootViewController selector:@selector(presentModalViewController:animated:) retainArguments:YES, vc, YES];
[invocation invokeOnMainThreadWaitUntilDone:NO]; // same result
}
}
else
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
}];
Run Code Online (Sandbox Code Playgroud)
错误信息:
bool _WebTryThreadLock(bool),0x6b21090:试图从主线程或Web线程以外的线程获取Web锁.这可能是从辅助线程调用UIKit的结果.现在崩溃......
multithreading objective-c uiwebview nsinvocation objective-c-blocks