How to make queue of API requests? So i've got some functions:
...
- (void) getUserBasicInfo:(NSString *)stringWithContestOfId;
- (void) getMyFriends;
- (void) getMyEducation;
...
I would like to make a function which call all this functions. How to take a pause until first functions finish? I tried to do something like this:
...
[currentUser getMyCurentCity];
while ([currentUser getFlag] != TRUE) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
[currentUser getMyCurentCity];
...
getFlag - functions which returns success-flag, which becomes true in:
- (void)request:(FBRequest *) request didReceiveResponse:(NSURLResponse *)response{
flag = TRUE;
NSLog(#"I have some information");
}
But finally when i used this method there was only one success request of many. Have you got more ideas how to do it? It will be perfect to do like : NSOperationQueue.
Thanks everybody...
[currentUser getMyCurentCity];
while ([currentUser getFlag] != TRUE) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
[currentUser setFlagFalse];
[currentUser getUserBasicInfo:#"me"];
while ([currentUser getFlag] != TRUE) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
[currentUser setFlagFalse];
Related
I tried these code in my Xcode, But just got message:4352 in my console.
I wander what is the parameter (void *)msg really mean?
- (void)launchThread
{
_myPort = [[NSMachPort alloc] init];
if (_myPort)
{
[_myPort setDelegate:self];
[[NSRunLoop currentRunLoop] addPort:_myPort forMode:NSDefaultRunLoopMode];
[NSThread detachNewThreadSelector:#selector(LaunchThreadWithPort:)
toTarget:self
withObject:_myPort];
}
}
- (void)LaunchThreadWithPort:(id)inData
{
NSPort *distantPort = (NSPort*)inData;
[distantPort sendBeforeDate:[NSDate date] msgid:12 components:nil from:nil reserved:123];
}
- (void)handleMachMessage:(void *)msg
{
NSLog(#"message:%d", *(int *)msg);
}
I have a function which takes a block as parameter:
typedef void (^ MyBlock)(int);
-(void)doTask:(MyBlock)theBlock{
...
}
I need to run above function on another thread, I want to use - performSelector:onThread:withObject:waitUntilDone: , my current code:
NSThread *workerThread = [[NSThread alloc] init];
[workerThread start];
[self performSelector:#selector(doTask:)
onThread:workerThread
withObject:???
waitUntilDone:NO];
BUT, How can I pass MyBlock parameter with this approach? (Please don't suggest GCD, I am wondering how can I do with my current code, is it possible?)
This answer assumes you are using ARC. If you are not then you need to do a little more, but overall the answer is the same.
BUT, How can I pass MyBlock parameter with this approach?
A block is an object, you don't need to do anything special. E.g.:
[self performSelector:#selector(doTask:)
onThread:workerThread
withObject:^(int arg){ NSLog(#"block passed: %d", arg); }
waitUntilDone:NO];
HTH
[self performSelector:#selector(someMethod)
onThread:[Your thread]
withObject:[your object]
waitUntilDone:NO];
-(void)someMethod
{
[self doTask:^(int intValue) {
// Do your task
}];
}
First create thread like this so that it is alive and you can call methods from that thread
-(void) myThreadMainMethod: (id) sender {
#autoreleasepool {
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
[runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
while (true) { // add your condition for keeping the thread alive
[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}
}
NSThread* workerThread = [[NSThread alloc] initWithTarget:self
selector:#selector(myThreadMainMethod:)
object:nil];
[workerThread start];
Then write something like this
-(void)doTask:(MyBlock)theBlock{
NSLog(#"do task called now execute the block");
theBlock(1);
}
MyBlock block1 = ^(int a) {
NSLog(#"integer %i", a);
};
[self performSelector:#selector(doTask:)
onThread:[NSThread mainThread]
withObject:block1
waitUntilDone:NO];
I use the code below to debounce the execution of the selector saveCurrentDocument.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (debounceTimer != NULL) {
[debounceTimer invalidate];
debounceTimer = NULL;
}
debounceTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(saveCurrentDocument) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:debounceTimer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
});
Currently, I noticed that dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) is creating another thread everytime an user types a letter in the app, so I tried to change it to this:
if (debounceQueue == nil) {
debounceQueue = dispatch_queue_create("com.testing.SaveQueue", NULL);
}
dispatch_async(debounceQueue, ^{
if (debounceTimer != NULL) {
[debounceTimer invalidate];
debounceTimer = NULL;
}
debounceTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(saveCurrentDocument) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:debounceTimer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
});
But now [debounceTimer invalidate] doesn't work anymore, and it's calling saveCurrentDocument every time.
Can anyone explain to me why this is happening?
It looks like you are adding the timer to the runloop twice. You should either remove the addTimer and run lines after instantiating debounceTimer, or alternatively you can use timerWithTimeInterval… instead of scheduledTimerWithTimeInterval…
I am using background threads with following pattern:
// Defined in .h-file as ivar
BOOL backgroundThreadIsAlive;
// .m file
static NSThread *backgroundThread = nil;
- (id)init
{
if (self = [super init])
{
if (backgroundThread == nil)
{
backgroundThreadIsAlive = YES;
backgroundThread = [[NSThread alloc] initWithTarget:self selector:#selector(threadMain:) object:nil];
[backgroundThread start];
}
}
return self;
}
- (void)threadMain:(id)data
{
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
[runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
while (backgroundThreadIsAlive)
{
[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}
My application sometimes crash with SIGSEGV in the line
[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
I am using ARC. The crash is not reproducible. Just found it, when diving into testflight and saw this is the most often crash I got. It seems to appear independently from iOS version (I support iOS5+) and device type.
May someone have a hint for me, what I do wrong?
Is there a better solution doing background-threads? (maybe using GCD)
Is there a way to reproduce those issues?
Thank you for your time and guidiance. :)
I have an application that creates a background thread for the network messages. The application works nearly perfectly unless the server it connects to closes the connection. I am unsure of why this happens but any advice is greatly appreciated. I've included the snippets of code that can be followed to the problem. If something is vague or more detail is needed please let me know.
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch(eventCode) {
case NSStreamEventErrorOccurred:
{
NSLog(#"NSStreamEventErrorOccurred");
[self Disconnect:self];
}
}
}
- (void)Disconnect:(id)sender {
[self performSelector:#selector(closeThread) onThread:[[self class]networkThread] withObject:nil waitUntilDone:YES];
[outputStream close];
[outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream release];
outputStream = nil;
}
+ (NSThread*)networkThread
{
// networkThread needs to be static otherwise I get an error about a missing block type specifier
static NSThread* networkThread = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
networkThread = [[NSThread alloc] initWithTarget:self selector:#selector(networkThreadMain:) object:nil];
[networkThread start];
});
return networkThread;
}
The hang up occurs on the return networkThread line. After executing that line the application seems to hang and freeze and I can't put my finger on why.
Thanks in advance.
EDIT
Here is the snippet of code for CloseThread for those interested
- (void)closeThread
{
/*if(!inputStream)
return;
[inputStream close];
[inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[inputStream release];
inputStream = nil;*/
}
I suggest changing:
[self performSelector:#selector(closeThread) onThread:[[self class]networkThread] withObject:nil waitUntilDone:YES];
to:
[self performSelector:#selector(closeThread) onThread:[[self class]networkThread] withObject:nil waitUntilDone:NO];
That is, don't wait.