Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/103.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
IOS阻止ui线程,直到singleton类中的JSON解析函数完成_Ios_Objective C_Xcode_Afnetworking_Blocking - Fatal编程技术网

IOS阻止ui线程,直到singleton类中的JSON解析函数完成

IOS阻止ui线程,直到singleton类中的JSON解析函数完成,ios,objective-c,xcode,afnetworking,blocking,Ios,Objective C,Xcode,Afnetworking,Blocking,我正在制作一个IOS应用程序,它应该在启动时从json提要收集数据。基本上,初始视图控制器是一个加载屏幕。在后台,在加载屏幕期间,它应该实例化我的singleton类,并调用json提要来用对象填充数组。当这个过程完成后,它会自动切换到我的主菜单 奇怪的是。我已经设置好了,效果很好,但5次中只有4次。有时它会直接进入菜单,在后台加载提要,这不是我想要的 有人能找到罪犯吗 以下是加载屏幕的我的视图控制器: #import "loadingViewController.h" #import "Sin

我正在制作一个IOS应用程序,它应该在启动时从json提要收集数据。基本上,初始视图控制器是一个加载屏幕。在后台,在加载屏幕期间,它应该实例化我的singleton类,并调用json提要来用对象填充数组。当这个过程完成后,它会自动切换到我的主菜单

奇怪的是。我已经设置好了,效果很好,但5次中只有4次。有时它会直接进入菜单,在后台加载提要,这不是我想要的

有人能找到罪犯吗

以下是加载屏幕的我的视图控制器:

#import "loadingViewController.h"
#import "Singleton.h"
#import "MBProgressHUD.h"

@interface loadingViewController ()

@end

@implementation loadingViewController

- (void)viewDidLoad {
    [super viewDidLoad];



    //[self performSegueWithIdentifier:@"launchSegue" sender:self];

    // Do any additional setup after loading the view.

    }

- (void)viewWillAppear:(BOOL)animated {

    Singleton *singletonManager = [Singleton singletonManager];

    [singletonManager loadJsonData];


}

- (void)viewDidAppear:(BOOL)animated {

    [self performSegueWithIdentifier:@"launchSegue" sender:self];

}

- (void)doSegue
{

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
这是我在singleton类中的实现:

implementation Singleton

@synthesize acts;

#pragma mark Singleton Methods

+ (id)singletonManager {
    static Singleton *singletonMyManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singletonMyManager = [[self alloc] init];
    });
    return singletonMyManager;
}

- (id)init {
    if (self = [super init]) {
        //someProperty = [[NSString alloc] initWithString:@"Default Property Value"];
        self.acts = [[NSMutableArray alloc] init];
    }
    return self;
}

- (BOOL) loadJsonData
{



    NSString     *urlString  = @"http://wwww.paaspop.nl/json/gettimetable";
    NSString     *callback   = @"api";
    NSDictionary *parameters = @{@"callback": callback};

    AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
    manager.securityPolicy.allowInvalidCertificates = YES;
    manager.responseSerializer = [CDLJSONPResponseSerializer serializerWithCallback:callback];
    __block NSDictionary* response = nil;
    AFHTTPRequestOperation* operation = [manager
                                         GET: urlString
                                         parameters: parameters
                                         success:^(AFHTTPRequestOperation* operation, id responseObject){
                                             response = responseObject;
                                             [self parseJSONData:response];
                                         }
                                         failure:^(AFHTTPRequestOperation* operation, NSError* error){
                                             NSLog(@"Error: %@", error);}
                                         ];
    [operation waitUntilFinished];
    return true;  



}

-(void) parseJSONData:(id) JSON
{
    NSArray *allActs = [JSON objectForKey:@"acts"];

    for (NSDictionary* dict in allActs) {
        //Create a pirate object where the json data can be stored
        Act *act = [[Act alloc] init];
        NSString *url;
        //Get the JSON data from the dictionary and store it at the Pirate object
        act.title = [dict objectForKey:@"title"];
        act.subtitle = [dict objectForKey:@"add"];
        act.jsontitle = [dict objectForKey:@"url_title"];
        act.favorite = FALSE;

        url = [dict objectForKey:@"photo"];

        NSURL *imageURL = [NSURL URLWithString:[dict objectForKey:@"photo"]];
        NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
        act.photo = [self imageWithImage:[UIImage imageWithData:imageData] scaledToWidth:320];

        NSLog(@"%f, %f",act.photo.size.width,act.photo.size.height);


        //Add the pirates to the array


        [self.acts addObject:act];


    }

}

-(UIImage*)imageWithImage: (UIImage*) sourceImage scaledToWidth: (float) i_width
{
    float oldWidth = sourceImage.size.width;
    float scaleFactor = i_width / oldWidth;

    float newHeight = sourceImage.size.height * scaleFactor;
    float newWidth = oldWidth * scaleFactor;

    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
    [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

- (NSMutableArray *) getActs {
    return self.acts;
}


- (void)dealloc {
    // Should never be called, but just here for clarity really.
}

我认为最好的方法是让-voidloadJsonData函数接受一个块,该块将在解析操作完成时执行。该块可以包含执行一个序列的代码。

如果您发现块很难使用,我认为您可以使用通知中心执行此任务

你发布这样的通知

[[NSNotificationCenter defaultCenter] postNotificationName:@"notificationName" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(methodCalledWhenReady:)
                                             name:@"notificationName"
                                           object:nil];
-(void) methodCalledWhenReady: (NSNotification *) notification
{
    //this is where you place the code that you want to execute only after 
      you finished fetching the data in the singleton class, in your case:

    [self performSegueWithIdentifier:@"launchSegue" sender:self];
}
在parseJSONData方法中的for循环之后

在主视图控制器中,应在viewDidLoad中添加一个观察者,如下所示

[[NSNotificationCenter defaultCenter] postNotificationName:@"notificationName" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(methodCalledWhenReady:)
                                             name:@"notificationName"
                                           object:nil];
-(void) methodCalledWhenReady: (NSNotification *) notification
{
    //this is where you place the code that you want to execute only after 
      you finished fetching the data in the singleton class, in your case:

    [self performSegueWithIdentifier:@"launchSegue" sender:self];
}
之后,您只需在主视图控制器中创建名为Henready的方法,该方法接收NSNotificationObjects,在这种情况下您并不真正需要它

[[NSNotificationCenter defaultCenter] postNotificationName:@"notificationName" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(methodCalledWhenReady:)
                                             name:@"notificationName"
                                           object:nil];
-(void) methodCalledWhenReady: (NSNotification *) notification
{
    //this is where you place the code that you want to execute only after 
      you finished fetching the data in the singleton class, in your case:

    [self performSegueWithIdentifier:@"launchSegue" sender:self];
}
您应该查看有关通知的更多信息


希望这有帮助

这里没有任何东西可以阻止它直接进入新屏幕。事实上,它每5次工作1次,其他4次都很奇怪

您已将MBProgressHud包含在文件中,但您没有对其执行任何操作。最好让用户界面保持活动状态,然后阻止用户进行操作,让应用程序看起来没有响应能力

在下载类中,您依赖waitUntilFinished。这将等待网络操作完成,然后返回。这不是等待json解析和图像操作发生


AFHTTPRequest库非常过时。这是一个很好的工作,但除非你有一些非常具体的较低层次的需要,它是远远涉及。NSUrlSession是苹果公司推出的一款新工具,功能强大,使用极其简单。

我认为NSNotifications很难调试,最好限制在许多未知收件人需要处理事件的情况下。我认为最好是a使用Aris的答案中的完成块,或者b创建一个简单的@protocol,并将视图控制器本身设置为singleton类的委托,以便在加载JSON数据时从该协议调用方法。