我在我的应用程序中使用了GCD和performSelectorOnMainThread:waitUntilDone,并且倾向于认为它们是可互换的 - 也就是说,performSelectorOnMainThread:waitUntilDone是GCD C语法的Obj-C包装器.我一直在考虑这两个命令是等价的:
dispatch_sync(dispatch_get_main_queue(), ^{ [self doit:YES]; });
[self performSelectorOnMainThread:@selector(doit:) withObject:YES waitUntilDone:YES];
Run Code Online (Sandbox Code Playgroud)
我不对吗?也就是说,performSelector*命令与GCD命令有区别吗?我已经阅读了很多关于它们的文档,但还没有看到明确的答案.
iphone multithreading objective-c grand-central-dispatch ios
最近,我需要一个可用于保证在特定串行调度队列上同步执行给定块的函数.有可能从已经在该队列上运行的东西调用这个共享函数,所以我需要检查这种情况,以防止从同步调度到同一队列的死锁.
我使用如下代码来执行此操作:
void runSynchronouslyOnVideoProcessingQueue(void (^block)(void))
{
dispatch_queue_t videoProcessingQueue = [GPUImageOpenGLESContext sharedOpenGLESQueue];
if (dispatch_get_current_queue() == videoProcessingQueue)
{
block();
}
else
{
dispatch_sync(videoProcessingQueue, block);
}
}
Run Code Online (Sandbox Code Playgroud)
此函数依赖于使用此函数dispatch_get_current_queue()来确定此函数正在运行的队列的标识,并将其与目标队列进行比较.如果匹配,它知道只运行块内联而不调度到该队列,因为该函数已在其上运行.
我听说过是否适当使用dispatch_get_current_queue()这样的比较是有争议的,我在标题中看到了这个措辞:
建议仅用于调试和记录目的:
代码不得对返回的队列做任何假设,除非它是全局队列之一或代码本身创建的队列.如果该队列不是dispatch_get_current_queue()返回的队列,则代码不得假设同步执行到队列是安全的死锁.
此外,在iOS 6.0中(但尚未针对Mountain Lion),GCD标题现在将此功能标记为已弃用.
听起来我不应该以这种方式使用这个功能,但我不确定我应该在它的位置使用什么.对于像上面那样针对主队列的函数,我可以使用[NSThread isMainThread],但是如何检查我是否在我的一个自定义串行队列上运行以便防止死锁?
这段代码
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSLog(@"Main Thread? %d", [NSThread isMainThread]);
});
Run Code Online (Sandbox Code Playgroud)
表明我在主线程中.即使这样做:
queue = dispatch_queue_create("nonMainQueue", NULL);
Run Code Online (Sandbox Code Playgroud)
仍然报告说我在主队列中.这似乎是因为我正在使用dispatch sync.
这是否意味着我的代码与不使用dispatch_sync相同?另外:如果dispatch_sync什么都不做的话,那又有什么意义呢?
如何确保我的函数仅在主线程上运行?(它更新UI元素)
这样的函数被认为是"坏"吗?
-(void)updateSomethingOnMainThread {
if ( ![[NSThread currentThread] isEqual:[NSThread mainThread]] )
[self performSelectorOnMainThread:_cmd withObject:nil waitUntilDone:NO];
else {
// Do stuff on main thread
}
}
Run Code Online (Sandbox Code Playgroud)
我这样写它是为了避免有第二个功能,最初我有这样的:
-(void)updateSomethingOnMainThread_real {
// Do stuff on main thread
}
-(void)updateSomethingOnMainThread {
[self performSelectorOnMainThread:@selector(updateSomethingOnMainThread_real) withObject:nil waitUntilDone:NO];
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试与Enttec USB DMX Pro进行通信.主要是接收DMX.
他们在这里发布了一个Visual C++版本,但我对如何转换为Obj-c感到有点困惑.Enttec写道,"使用适用于Mac的FTDI库与PRO交谈,并参考D2XX编程指南打开并与设备通信." Objective-C的所有示例应用程序都在那里?有没有简单的方法与Enttec DMX USB Pro进行通信?
我试图在主线程上执行此操作:
[curItem.mButton setBackgroundImage:newArt forState:UIControlStateNormal];
Run Code Online (Sandbox Code Playgroud)
所以我这样做......
cWrapperObject* obj = [cWrapperObject alloc];
[obj setupParams :curItem.mButton :newArt];
[obj performSelectorOnMainThread:@selector(setImageForButton) withObject:nil waitUntilDone:YES];
Run Code Online (Sandbox Code Playgroud)
我觉得这很糟糕,有没有人对我如何处理这种方式有任何建议?
所以我有这个代码:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
//Bunch of code
NSLog(@"Test");
});
Run Code Online (Sandbox Code Playgroud)
它运行并立即返回nslog.但是代码的结果只会在屏幕上出现几秒延迟.在这里使用nslog是否存在问题,这意味着它通常会被调用,这使得它看起来很快,而实际上并非如此.我很困惑这个延迟来自哪里,因为NSLog正好在所有运行的代码的末尾.
另外,我的问题的另一个解决方案是,有可能在调用每个方法时得到一个NSLog(有点像我想的NSZombiesEnabled)所以我可以确保没有一些我没注意到的甜点响应我的应用程序的时间?
我确信这是我的iOS/ObjC noob-ness的一个问题...
我有一个带有条目的UITableView,当用户选择一行时,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
...
[self.twitter sendUpdate:[self getTweet]];
Run Code Online (Sandbox Code Playgroud)
和
- (NSString *)sendUpdate:(NSString *)text;
{
NSLog(@"showing HUD");
self.progressSheet = [MBProgressHUD showHUDAddedTo:[[UIApplication sharedApplication] keyWindow] animated:YES];
self.progressSheet.labelText = @"Working:";
self.progressSheet.detailsLabelText = text;
// Build a twitter request
TWRequest *postRequest = [[TWRequest alloc] initWithURL:
[NSURL URLWithString:@"http://api.twitter.com/1/statuses/update.json"]
parameters:[NSDictionary dictionaryWithObject:text
forKey:@"status"] requestMethod:TWRequestMethodPOST];
// Post the request
[postRequest setAccount:self.twitterAccount];
// Block handler to manage the response
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
NSLog(@"Twitter response, HTTP response: %i", [urlResponse statusCode]);
NSLog(@"hiding …Run Code Online (Sandbox Code Playgroud) 我想要一种简单的方法来在一个方法的开头删除代码,该方法将强制该方法仅在主线程上运行(因为该方法更新了UI元素).
目前,我有类似的东西:
if (![NSThread isMainThread]){
[self performSelectorOnMainThread:_cmd withObject:_results waitUntilDone:NO];
return;
}
Run Code Online (Sandbox Code Playgroud)
但是我想要一种方法将它包含在一个宏中而不必输入方法的参数.看起来应该有一些方法来迭代传递给当前方法的参数列表并创建一个NSInvocation或类似的.有什么想法吗?
我相信我知道调用它时调度队列在做什么,但是我不确定何时应该确切地使用它,以及当我使用它时它的优点是什么。
如果我的理解是正确的,DispatchQueue.main.async { // code }将调度包含在闭包中的代码以异步方式在主调度队列上运行。主队列具有最高优先级,通常保留用于更新UI以最大化App响应能力。
我感到困惑的地方是:更新调度队列闭包中的UI元素与只在闭包外的同一位置编写代码有什么区别?在加载了方法的视图主体中执行代码而不是将其发送到调度队列是否更快?如果没有,为什么?
代码示例:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
}
}
Run Code Online (Sandbox Code Playgroud)
与:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.async {
updateUI()
}
}
}
Run Code Online (Sandbox Code Playgroud)
哪个会更快更新UI?
ios ×7
objective-c ×7
iphone ×4
asynchronous ×1
dmx512 ×1
ftdi ×1
macos ×1
multitasking ×1
swift ×1
xcode ×1