Recently, I encountered a problem during iOS development: some operations must be allowed after an initialization operation. However, the execution time of these operations may be faster than the initialization operation. If you do not wait for the initialization operation to be executed, these operations will be lost.
To solve this problem, I have come up with two solutions: the first is to determine whether initialization has been performed before performing these operations, if Initialization is not performed, use an array queue to store operation parameters and call methods. Wait until the initialization is complete and check the stored operations in the array queue for calling and clearing the queue. However, a problem with this method is that the parameters passed in the operation and call method references must be maintained by yourself, which undoubtedly brings a certain amount of work and risks to you, A slight carelessness may cause memory leakage.
Therefore, the second solution is to use the serial queue and semaphore to control the operation execution. The idea of this solution is to create a serial queue for all operations. However, the first operation to join the queue is a waiting signal operation. The initial value of this signal is 0, and a signal will not be sent until the initialization operation is complete to notify this operation. Therefore, the queue is always in the blocking state when Initialization is not complete. Therefore, operations will be executed immediately when they enter the queue, but they will not be executed until the initialization signal comes over.
To verify this idea, I created an application project and defined the operation queue _ quque and semaphore _ sema in ViewController, as follows:
- @interface ViewController : UIViewController
-
- {
-
- @private
-
- dispatch_queue_t _queue;
-
- dispatch_semaphore_t _sema;
-
- }
-
-
- @end
Create operation queue during initialization
- - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
-
- {
-
- if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
-
- {
-
- _queue = dispatch_queue_create("cn.vimfung.demo", DISPATCH_QUEUE_SERIAL);
-
- }
-
-
-
- return self;
-
- }
Three buttons are defined in ViewController: DoSomething, Signal, and Wait. DoSomething indicates the executed operation. Signal can perform operations for the notification blocking queue. Wait blocks the current queue.
- - (void)viewDidLoad
-
- {
-
- [super viewDidLoad];
-
- // Do any additional setup after loading the view, typically from a nib.
-
-
-
- UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
-
- [btn setTitle:@"DoSomething" forState:UIControlStateNormal];
-
- [btn sizeToFit];
-
- [btn addTarget:self action:@selector(doSomethingHandler:) forControlEvents:UIControlEventTouchUpInside];
-
- [self.view addSubview:btn];
-
-
-
- UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
-
- [btn1 setTitle:@"Signal" forState:UIControlStateNormal];
-
- [btn1 sizeToFit];
-
- [btn1 addTarget:self action:@selector(signalHanlder:) forControlEvents:UIControlEventTouchUpInside];
-
- btn1.frame = CGRectMake(0.0, 50.0, btn1.frame.size.width, btn1.frame.size.height);
-
- [self.view addSubview:btn1];
-
-
-
- UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
-
- [btn2 setTitle:@"Wait" forState:UIControlStateNormal];
-
- [btn2 sizeToFit];
-
- [btn2 addTarget:self action:@selector(waitHanlder:) forControlEvents:UIControlEventTouchUpInside];
-
- btn2.frame = CGRectMake(0.0, 100.0, btn2.frame.size.width, btn2.frame.size.height);
-
- [self.view addSubview:btn2];
-
- }
-
-
-
- - (void)doSomethingHandler:(id)sender
-
- {
-
- dispatch_async(_queue, ^{
-
- NSLog(@"do something");
-
- });
-
- }
-
-
-
- - (void)signalHanlder:(id)sender
-
- {
-
- dispatch_semaphore_signal(_sema);
-
- }
-
-
-
- - (void)waitHanlder:(id)sender
-
- {
-
- if (_sema)
-
- {
-
- dispatch_release(_sema);
-
- }
-
- _sema = dispatch_semaphore_create(0);
-
- dispatch_async(_queue, ^{
-
- dispatch_semaphore_wait(_sema, DISPATCH_TIME_FOREVER);
-
- });
-
- }
After running, click Wait to block the queue. Then, no log information is displayed when you click DoSomething. After you click Signal, the previously clicked DoSomething will print the information one by one.
This solution is feasible and easier to operate.