标签: grand-central-dispatch

使用GCD从Cocoa应用程序运行Python脚本

我正在尝试从Cocoa应用程序运行Python脚本.它在主线程上运行得很好,但是我希望它在后台运行,并发GCD队列.

我正在使用以下方法来设置运行Python脚本的管理器类:

- (BOOL)setupPythonEnvironment {
    if (Py_IsInitialized()) return YES;

    Py_SetProgramName("/usr/bin/python");
    Py_Initialize();

    NSString *scriptPath = [[NSBundle mainBundle] pathForResource:@"MyScript"     ofType:@"py"];

    FILE *mainFile = fopen([scriptPath UTF8String], "r");
    return (PyRun_SimpleFile(mainFile, (char *)[[scriptPath lastPathComponent] UTF8String]) == 0);
}
Run Code Online (Sandbox Code Playgroud)

之后,使用manager类的共享单例实例从以下实例方法(重复)调用脚本:

- (id)runScriptWithArguments:(NSArray *)arguments {
    return [NSClassFromString(@"MyScriptExecutor") runWithArguments:arguments];
}
Run Code Online (Sandbox Code Playgroud)

上面的Objective-C代码挂钩到以下Python代码:

from Foundation import *

def run_with_arguments(arguments):
#    ...a long-running script

class MyScriptExecutor(NSObject):
    @classmethod
    def runWithArguments_(self, arguments):
        return run_with_arguments(arguments)
Run Code Online (Sandbox Code Playgroud)

当我总是从主队列运行上述Objective-C方法时,这可以工作,但是当从任何其他队列运行时,脚本返回null.有人可以解释一下,如果我想要做的事情不被支持,是否有一个好的方法呢?

经常调用Python脚本并运行很长时间,因此在主线程上执行此操作会太慢,而是从串行队列中运行它.另外,我想尽可能地在Objective-C中包含并发代码.

谢谢,

python objective-c grand-central-dispatch

15
推荐指数
1
解决办法
7674
查看次数

我应该如何在iOS中使用GCD dispatch_barrier_async(似乎在其他块之前而不是之后执行)

我正在尝试在iOS5中同步以下代码:

  1. 一个对象有一个方法,它发出一个HTTP请求,从中获取一些数据,包括一个图像的URL
  2. 一旦数据到达,文本数据将用于填充CoreData模型
  3. 同时,调度第二个线程异步下载图像; 当图像已经缓存并在CoreData模型中可用时,此线程将通过KVO发送信号到viewController.
  4. 由于图像下载需要一段时间,我们会立即将具有所有属性的CoreData对象返回给调用者.
  5. 此外,当第二个线程完成下载时,可以保存CoreData模型.

这是(简化)代码:

- (void)insideSomeMethod
{
    [SomeHTTPRequest withCompletionHandler:
     ^(id retrievedData) 
     {
         if(!retrievedData)
         {
             handler(nil);
         }

         // Populate CoreData model with retrieved Data...

         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
             NSURL* userImageURL = [NSURL URLWithString:[retrievedData valueForKey:@"imageURL"]];
             aCoreDataNSManagedObject.profileImage = [NSData dataWithContentsOfURL:userImageURL];
         });

         handler(aCoreDataNSManagedObject);
         [self shouldCommitChangesToModel];
     }];
}

- (void)shouldCommitChangesToModel
{
    dispatch_barrier_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        NSError *error = nil;
        if(![managedObjectContext save:&error]) 
        {
            //  Handle error
        }  
    });
}
Run Code Online (Sandbox Code Playgroud)

但是,正在发生的是基于屏障的保存块总是在图像加载块之前执行.那是,

dispatch_barrier_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            NSError *error = nil;
            if(![managedObjectContext save:&error]) 
            {
                //  Handle error
            } …
Run Code Online (Sandbox Code Playgroud)

concurrency cocoa-touch grand-central-dispatch ios objective-c-blocks

15
推荐指数
1
解决办法
2万
查看次数

使用GCD加载异步UITableViewCell图像

我目前正在尝试加载Flickr Photo的UITableView列表(cs193p iOS Stanford,作业5).为了避免UI阻塞事件,我将每个单元的缩略图下载推迟到不同的队列(但是在主队列中更新UI).此代码不会异步加载图像,但是一旦我单击UITableViewCell行,就会添加缩略图.(见下面的截图).知道我做错了什么吗?

PS:我已经看过其他一些stackoverflow问题和Apple的LazyTableImages示例,但我仍然相信这是达到预期结果的最简洁方法.

谢谢!

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Photo List Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Configure the cell
    NSDictionary *photo = [self.photoList objectAtIndex:indexPath.row];


    if (photo != nil) {
        if ([[photo objectForKey:@"title"] length] > 0) {
            cell.textLabel.text = [photo objectForKey:@"title"];
        } else if ([[[photo objectForKey:@"description"] objectForKey:@"_content"] length] > 0) {
            cell.textLabel.text = [[photo objectForKey:@"description"] objectForKey:@"_content"];
        } else {
            cell.textLabel.text = @"Unknown";
        }
    }
    cell.imageView.image = [[UIImage alloc] initWithCIImage:nil];

    // Fetch …
Run Code Online (Sandbox Code Playgroud)

uitableview grand-central-dispatch ios

15
推荐指数
1
解决办法
1万
查看次数

图像下载后更新单元格高度

我正在显示一些文本和图像UITableView.首先下载图像.从图像下载之前,我不知道图像的大小,所以我最初放了UIImageView一些固定的大小.当下载图像时,我调整了大小UIImageView.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

// Download image

    dispatch_async(dispatch_get_main_queue(), ^{

    // UIImageView resizing  
    });  
});
Run Code Online (Sandbox Code Playgroud)

所有这些都发生在cellForRowAtIndexPath.
我在这里
遇到的问题是:1.如何更新细胞的高度?考虑到单个单元格中可能存在许多图像.所以我需要在下载时更改底部图像的位置.
2.我尝试使用UITableView beginUpdatesendUpdates,但滚动到单元格的顶部,给用户带来糟糕的体验.

这就是uload在reloadData上的样子.有5个图像需要下载:UITableView reloadData之后的UI体验

uitableview uiimageview grand-central-dispatch ios

15
推荐指数
1
解决办法
7710
查看次数

Dispatch group - 无法通知主线程

在GCD上阅读Swift 3 evolution之后,我正在尝试创建调度组.问题是group.notify(queue:当我DispatchQueue.main作为队列传递时不通知,尽管它确实适用于后台队列.

此外,我不确定我的语法是否正确,因为我试图将代码从Swift 2转换为Swift 3.

typealias CallBack = (result: Bool) -> Void
func longCalculations (completion: CallBack) {

let backgroundQ = DispatchQueue.global(attributes: .qosBackground)

    let group = DispatchGroup()  
    var fill:[Int] = [] 
    for item in 0...200 {
        group.enter() 
        if item > 50 {
            fill.append(item)
        }
        group.leave() 
    }

//Below in the notify argument If I pass `backgroundQ`, it seems to work correctly but not when DispatchQueue.main is passed.
Run Code Online (Sandbox Code Playgroud)

此代码不起作用

group.notify(queue: DispatchQueue.main, execute: {
    completion(result: true)
    })
 }
Run Code Online (Sandbox Code Playgroud)

这工作正常 …

grand-central-dispatch swift swift3

15
推荐指数
1
解决办法
1万
查看次数

Grand Central Dispatch如何真正使用操作系统?

我对GCD如何工作有一个很好的想法,但我想更多地了解被吹捧的"操作系统管理"内部.几乎所有关于Grand Central Dispatch如何与"操作系统"协同工作的技术解释都完全不同.我会解释一些我的发现.

"它是一个守护程序,它是操作系统的全局,可以在许多核心上分配任务."

我并不傻到相信这一点.

"内核中内置了支持以了解所有GCD应用程序.GCD应用程序与内核协同工作,就如何管理应用程序中的线程做出逻辑决策."

听起来这种同步方案比仅仅管理应用程序中的逻辑要慢得多.

"GCD仅存在于应用程序中,并使用当前系统负载作为其行为的度量标准."

这对我来说听起来更真实,但我只在一个地方看到了这样的陈述.

这里到底发生了什么?它只是一个图书馆,还是整个"系统"?

objective-c grand-central-dispatch ios

14
推荐指数
1
解决办法
1736
查看次数

将块保留在字典中

我有自己的方法,以块作为参数.我想跟踪NSDictionary中的那个块.将块添加到字典的最佳方法是什么?

我尝试了这段代码但是在执行下面的行(setObject ...)后,字典仍然是空的.我认为这是因为该块不是NSObject类型.但是这样做的正确方法是什么?

- (void)startSomething:(NSURLRequest*)request block:(void (^)(NSURLResponse*, NSData*, NSError*))handler {

    NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];

    [pendingRequests setObject:handler forKey:connection];
}
Run Code Online (Sandbox Code Playgroud)

编辑:

没关系.我不知道我在想什么.3分:

  1. 块是objc对象
  2. 错字:setObject应该是setValue
  3. forKey是一个字符串,因此它应该是[连接描述]或类似的东西

无论如何我现在解决了我的问题:

- (void)startSomething:(NSURLRequest*)request block:(void (^)(NSURLResponse*, NSData*, NSError*))handler {

    NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
    [pendingRequests setValue:handler forKey:[connection description]];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {

        void (^handler)(NSURLResponse*, NSData*, NSError*);
        handler = [pendingRequests valueForKey:[connection description]];
        handler(nil, nil, nil);
    });
}
Run Code Online (Sandbox Code Playgroud)

nsdictionary grand-central-dispatch ios objective-c-blocks

14
推荐指数
3
解决办法
1万
查看次数

ios:队列在后台阻塞,并在网络可用时执行

我正在使用parse.com API开发一个应用程序(托管后端提供API以在其服务器上保存数据).我希望能够在线和离线无缝使用该应用程序.为此,我需要使用一个队列,我可以放置需要网络访问的块.当网络确实可用时,应该串行执行这些块,当网络脱机时,应该暂停队列处理.

当网络变得可用/不可用时,我正在考虑将GCD用于暂停/恢复.我想知道是否有更好的选择?如果将应用程序放在后台,这会有效吗?这里的一个例子是,当网络不可用(排队等待)然后将应用程序置于后台时,用户会保存一些数据.现在,当网络可用时,是否可以自动在后台进行保存?

queue grand-central-dispatch reachability ios parse-platform

14
推荐指数
1
解决办法
5072
查看次数

使用dispatch_async或performSelectorOnMainThread在主线程上执行UI更改?

可能重复:
Grand Central Dispatch(GCD)与performSelector - 需要更好的解释

要在主线程上执行"stuff",我应该使用dispatch_async还是performSelectorOnMainThread?是否有首选方式,正确/错误和/或最佳做法?

示例:我在NSURLConnection sendAsynchronousRequest:urlRequest方法块中执行某些逻辑.因为我正在做主要视图的东西,比如呈现UIAlertView我需要UIAlertView在主线程上显示.为此,我使用以下代码.

[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

    // code snipped out to keep this question short

    if(![NSThread isMainThread]) 
    {
        dispatch_async(dispatch_get_main_queue(), ^{
                    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Oops!" message:@"Some Message" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
                    [alertView show];
        });
    }
}];
Run Code Online (Sandbox Code Playgroud)

在同一个if(![NSThread isMainThread])声明中,我也称之为一些自定义方法.问题是,我应该dispatch_async使用上面使用的方法还是更好地使用performSelectorOnMainThread?例如,下面的完整代码:

[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

    // code snipped …
Run Code Online (Sandbox Code Playgroud)

asynchronous objective-c nsthread grand-central-dispatch ios

14
推荐指数
1
解决办法
3万
查看次数

DispatchQueue.main.sync返回exc_bad_instruction Swift 3

我想在我的应用程序中显示一个ActivityIndi​​catorView,但是当我sync从主线程调用该方法时,应用程序崩溃并出现错误:exc_bad_instruction (code=exc_i386_invop subcode=0x0) 我正在使用xcode 8.0和swift 3

有人可以帮帮我吗?

 func POST(endpoint:NSString!,body:NSString!,vc:UIViewController? = nil)->NetworkResult{
    let result = NetworkResult()
    DispatchQueue.main.sync {
        self.displayActivityIndicator(viewController: vc)
    }
    let urlStr = self.url.appending(endpoint as String).appending(self.getHashAutenticacao() as String)
    print(urlStr)
    let request = NSMutableURLRequest(url: URL(string: urlStr)!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 20)
    print(request.debugDescription)
    request.setValue("application/json", forHTTPHeaderField: "Accept")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "POST"
    request.httpBody = body.data(using: String.Encoding.utf8.rawValue, allowLossyConversion: true)

    // send the request
    var data: NSData!
    do {
        data = try NSURLConnection.sendSynchronousRequest(request as URLRequest, returning: &self.response) as NSData!
    } catch let …
Run Code Online (Sandbox Code Playgroud)

grand-central-dispatch ios swift swift3

14
推荐指数
3
解决办法
1万
查看次数