4

当应用程序启动时,我正在以编程方式创建许多具有透明背景颜色的复杂 UIView,每个都是应用程序中的“屏幕”(必须这样,因为下面有动画背景)。这会导致应用在静态启动图像上停留很长时间(大约 4 秒)。

我想在显示动画时创建所有 UIView。我无法在后台线程上创建 UIView。我怎样才能做到这一点?

尝试1:

-(void)viewDidLoad {

    [super viewDidLoad];


    dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        UIView *baseView = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 200, 100)];
        [baseView setBackgroundColor:[UIColor blueColor]];

        UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 10, 180, 80)];
        [button setBackgroundColor:[UIColor redColor]];
        [button setTitle:@"button" forState:UIControlStateNormal]; //doesn't work
        [baseView addSubview:button];

        dispatch_async( dispatch_get_main_queue(), ^{ //Finished

            [self.view addSubview:baseView];
        });

    });
}

添加了按钮,但从未设置标题。点击后出现。

4

2 回答 2

2

感谢帮助。这是我测试并完美运行的最终解决方案。

我创建了一个任务管理器类,FCTaskManager:

//Header File

typedef void (^TaskBlock)(void);
typedef void (^TaskCompletedBlock)(void);

@interface FCTaskManager : NSObject

-(void)performUITask:(TaskBlock)taskBlock completionBlock:(TaskCompletedBlock)taskCompletedBlock;
-(void)performBackgroundTask:(TaskBlock)taskBlock completionBlock:(TaskCompletedBlock)taskCompletedBlock;

@end



//Implementation

#import "FCTaskManager.h"

@implementation FCTaskManager

-(void)performUITask:(TaskBlock)taskBlock completionBlock:(TaskCompletedBlock)taskCompletedBlock {

    dispatch_async( dispatch_get_main_queue(), ^{

        @autoreleasepool {

            taskBlock();

            dispatch_async( dispatch_get_main_queue(), ^{

                taskCompletedBlock();
            });
        }
    });
}

-(void)performBackgroundTask:(TaskBlock)taskBlock completionBlock:(TaskCompletedBlock)taskCompletedBlock {

    dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        @autoreleasepool {

            taskBlock();

            dispatch_async( dispatch_get_main_queue(), ^{

                taskCompletedBlock();
            });
        }
    });
}

@end

然后我可以像这样使用任务管理器:

-(void)viewDidLoad {

    [super viewDidLoad];

    //Create taskManager
    taskManager = [[FCTaskManager alloc] init];

    //Create UIViews, etc WITHOUT blocking main queue
    [taskManager performUITask:^{

        button = [[UIButton alloc] initWithFrame:CGRectMake(30, 30, 300, 300)];
        [button setBackgroundColor:[UIColor redColor]];
        [button setTitle:@"Working" forState:UIControlStateNormal];
        [button addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];

    } completionBlock:^{

        NSLog(@"CREATED BUTTON");

        [self.view addSubview:button];
    }];
}
于 2013-07-25T12:36:30.033 回答
2

UIViews 在正常使用中不是线程安全的,所有的交互都应该发生在主线程上。也就是说,您应该能够在某个后台线程(调度队列)上创建视图、修改其参数、设置复杂的背景颜色等——只要视图没有连接到任何东西(从而接收来自 iOS 的事件)。一旦视图完全设置和连接,然后将一个块与它一起分派到主队列,然后才将其作为子视图添加到其他视图。

我要做的是在设置了我的初始视频剪辑后将所有这些工作分派到正常的优先级队列。当所有视图都已发布回主队列(因此​​这项工作已完成)时,您可以停止视频并开始与用户交互。

于 2013-07-24T18:16:58.153 回答