返回从块内部设置的NSString [英] Return NSString which is set from inside a block

查看:66
本文介绍了返回从块内部设置的NSString的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个看起来像这样的方法:

I have a method which looks like this:

-(NSString *)getCityFromLocation:(CLLocation *)location {

    __block NSString *city;

    CLGeocoder *geocoder = [[CLGeocoder alloc] init];

    [geocoder reverseGeocodeLocation: location completionHandler:
     ^(NSArray *placemarks, NSError *error) {

         //Get address
         CLPlacemark *placemark = [placemarks objectAtIndex:0];

         city = [placemark.addressDictionary objectForKey:@"City"];

         NSLog(@"city 1: %@", city);

     }];

    return city;
}

我这样称呼它:

NSString *city = [self getCityFromLocation:currentLocation];

NSLog(@"city 2: %@", city);

在NSLog中,我得到:

In NSLog, I get:

city 2: (null)
city 1: London

问题很明显-它在运行块之前就返回了.我如何才能使其按预期工作,在哪里可以返回该块产生的值?

The problem is obvious - it's returning before it's ran the block. How can i get this to work as intended, where it can return the value produced by the block?

推荐答案

您在这里使用的异步方法(例如reverseGeocodeLocation:)通常是有充分理由的-它们需要时间才能完成.有鉴于此,您首先应该考虑设计并确定您是否真的应该尝试以同步方式使用异步方法.

Asynchronous methods, such as reverseGeocodeLocation: you have used here, are normally that for a very good reason - they take time to complete. In that light you should first consider your design and determine whether you really should be trying to use an asynchronous method in a synchronous manner.

如果您确定需要执行此操作,则一种解决方案是使用信号量.在调用reverseGeocodeLocation:之前,请创建带有dispatch_semaphore_create的信号灯(GCD的一部分,在本手册的第3节中).然后在您的代码块内,使用dispatch_semaphore_signal指示字符串已准备好,并在代码块dispatch_semaphore_wait外部进行阻塞,直到字符串准备好.

If you do decide you need to do this one solution is to use a semaphore. Before the call to reverseGeocodeLocation: create a semaphore with dispatch_semaphore_create (part of GCD, in section 3 of the manual). Then within your block you use dispatch_semaphore_signal to indicate that the string is ready, and outside your block dispatch_semaphore_wait to block until the string is ready.

您为执行此操作而修改的代码,直接键入答案而不执行:

Your code modified to do this, typed directly into the answer and not executed:

#include <dispatch/dispatch.h>

-(NSString *)getCityFromLocation:(CLLocation *)location
{

   __block NSString *city;

   dispatch_semaphore_t sema = dispatch_semaphore_create(0);

   CLGeocoder *geocoder = [[CLGeocoder alloc] init];

   [geocoder reverseGeocodeLocation: location completionHandler:
      ^(NSArray *placemarks, NSError *error)
      {
         //Get address
         CLPlacemark *placemark = [placemarks objectAtIndex:0];

         city = [placemark.addressDictionary objectForKey:@"City"];
         dispatch_semaphore_signal(sema); // string is ready
      }
   ];

   dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); // wait for string
   dispatch_release(sema); // if you are using ARC & 10.8 this is NOT needed
   return city;
}

但是请认真考虑,这是否是您应该做的事情.

But seriously, consider carefully whether this is what you should be doing.

HTH.

这篇关于返回从块内部设置的NSString的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆