Here's how I start the code:
m_searchTimer = [[NSTimer timerWithTimeInterval:0.5 target:self selector:#selector(launchRequest:) userInfo:nil repeats:FALSE] retain];
[[NSRunLoop mainRunLoop] addTimer:m_searchTimer forMode:NSDefaultRunLoopMode];
then in my -(void)launchRequest method:
- (void)launchRequest:(NSTimer *)timer
{
ASIHTTPRequest *req = [[[m_twitterQueue operations] lastObject] copy];
[m_twitterQueue cancelAllOperations];
[m_twitterQueue addOperation:req];
[m_twitterQueue go];
}
once I reach the - (void)go; method, I get the bad access.
Any idea is welcomed
I have found the issue.
Using ASIHTTPRequest, there is a #property named
shouldCancelAllRequestsOnFailure //Default is YES
By leaving it on, you add a request while cancelling it which makes the queue crash.
Turning it False solved the issue.
Related
I need to set timeout 15sec or 30 sec with UIRequest, but it always takes default one. Is there any way to set minimum timeout to connection.
This answer explains about the minimum value of timeoutInterval of an NSURLRequest object. If you need a smaller value, then you may do so with starting an NSTimer with the desired time and in the firing method of the timer, you cancel the connection of your NSURLConnection object. As in:
//....
connection = [[NSURLConnection connectionWithRequest:request delegate:self] retain];
[request release];
[connection start];
if (timer == NULL) {
timer = [NSTimer scheduledTimerWithTimeInterval: TimeOutSecond
target: self
selector: #selector(cancelURLConnection:)
userInfo: nil
repeats: NO];
[timer retain];
}
- (void)cancelURLConnection:(NSTimer *)timerP {
[connection cancel]; //NSURLConnection object
NSLog(#"Connection timeout.");
[timer invalidate];
}
There seems to be a problem with setting the timeout interval property at construction time:
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:240.0];
Instead set it AFTER construction:
request.timeoutInterval = 70;
Also note that there seem to be some limitations to how low you can set the interval. Read this post for more information:
https://devforums.apple.com/message/108087#108087
POST requests have a timeout minimum which is 4 minutes, I believe. The most secure way is to start a NSTimer and cancel the request when the timeout fires.
I use a NSThread in order to download videos and images from a server side.It work looks and works great except the fact that when the downloading is done my GUI gets blocked until the download is complete.When the download is finished it takes a few seconds to work again.
this is how the server request is done:
- (void) repeatRequest{
NSLog(#"repeatRequest");
[NSThread detachNewThreadSelector:#selector(backgroundRequest) toTarget:self withObject:nil];
}
- (void) backgroundRequest{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSURL *url = [NSURL URLWithString:myURLStr];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
[pool drain];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
//do things
}
IMPORTANTAnd I also tried to start the ASIHTTPRequest from the GUI thread but with the same behaviour.
Any idea about what could be wrong?
EDIT:
- (void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
//internetReachable = [[Reachability reachabilityForInternetConnection] retain];
if(timer1 == nil)
{
timer1 = [NSTimer scheduledTimerWithTimeInterval:60.0 target:self selector: #selector(repeatRequest) userInfo: nil repeats: YES];
}
}
Try to run synchronous ASIHTTPRequest in your background thread, and handle results not in delegate method (requestFinished), but after [request startSynchronous];
I don't know anything about ASIHTTPRequest but i would assume its -startAsynchronous method already handles the background downloading for you. It all likelihood, it is returning immediately and your new thread is exiting. Also, you should just use [pool release] at the end of a thread method instead of [pool drain], it will be drained upon release, and you won't be leaking an NSAutoReleasePool. Does ASIHTTPRequest have a -startSynchronous (or just plain -start) method? Try using that within -backgroundRequest, as it should block the premature exit of that thread.
i have some animation to be played at some point in time. that time is decided by some thread running in the backgroud. now i want to play the animation regardless of which screen the user is on. here is screen hierarchy.
login-->homescreen(thread starts running from viewdidload).
from home screen the user may navigate to any other screen and i want the animation to be played. right now i have the animationviewcontrller a membervariable in the homescreen and i am calling it by allocing and initing and pushing and popping when animation is done. and it works only 10% of the time. i have tried performselectoronmainthread and its still the same.
How do i redesign my code such that is plays on anyscreen.
here is my code for my thread.
[self startTimerThread]; // in viewdidload
-(void)startTimerThread
{
homescreenthread = [[NSThread alloc] initWithTarget:self selector:#selector(setupTimerThread) object:nil];
[homescreenthread start];
}
-(void)setupTimerThread
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSTimer* timer = [NSTimer timerWithTimeInterval:5
target:self
selector:#selector(findnewmessages)
userInfo:nil
repeats:YES];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSRunLoopCommonModes];
//[runLoop addTimer:timer forModes:NSRunLoopCommonModes];
[runLoop run];
[pool release];
}
-(void)findnewmessages
{//finding message from server here. i am using the following request
NSData *serverReply = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *replyString = [[NSString alloc] initWithBytes:[serverReply bytes] length:[serverReply length] encoding: NSASCIIStringEncoding];
//i have omitted lot of other code.
}
use the delegate of the app to display the animation view.
id appDelegate = [UIApplication sharedApplication].delegate;
[appDelegate.m_window addSubview:viewController.view];
Also if you are tying to draw anything on the screen it should be done on main thread.
Please let me know if it helps.
Hi I am new to objective c. I am trying to make an app for iphone. I have a button on my view, and the click on which the function playSound is called. This is working properly. It does plays the sound that i want it to.
Now the problem is with the timer. I want the timer to start on the click on the same button, and the timer value will be displayed in a label. I am not very clear with the NSTimer itself either yet. I guess i am doing something wrong here. Can anyone help me with this.
-(IBAction)playSound { //:(int)reps
NSString *path = [[NSBundle mainBundle] pathForResource:#"chicken" ofType:#"wav"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: path];
AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
theAudio.delegate = self;
[theAudio play];
[self startTimer];
}
- (void)startTimer {
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(targetMethod) userInfo:nil repeats:YES];
labelA.text = [NSString stringWithFormat:#"%d", timer];
}
Using the code above, when i click on the button, it plays the sound, and then my app closes.
Thanks
Zeeshan
This line:
labelA.text = [NSString stringWithFormat:#"%d", timer];
makes absolutely no sense. The timer will call the method you specify as the selector in scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: when it fires so you have to implement that method and update your label there. The first line of startTimer is almost correct, but the selector must include a colon (because it denotes a method that takes one parameter):
- (void)startTimer {
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timerFired:) userInfo:nil repeats:YES];
}
Note that I named the selector timerFired: so we have to implement that method. If you want the timer to increment a counter, you will have to do that in this method, too:
- (void)timerFired:(NSTimer *)timer {
static int timerCounter = 0;
timerCounter++;
labelA.text = [NSString stringWithFormat:#"%d", timerCounter];
}
Don't forget to invalidate the timer later when you no longer need it.
How can I set a timeout when I am parsing a feed using initWithContentsOfURL. Sometimes our feeds return a blank response and then it will just try to parse the feed forever. I want to set a timeout of 30 seconds or so that will pop up a UIAlertView and then try and reparse the feed.
NSURL *feedURL = [[NSURL alloc] initWithString:URL];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:feedURL];
[parser setDelegate:self];
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
First approach: using a delayed selector
Probably the simplest way to do this is to use NSObject's performSelector:withObject:afterDelay: method. You can define some method parsingDidTimeout as such:
- (void)parsingDidTimeout {
if(self.parsingDidComplete == NO) {
[self.parser abortParsing];
// Create your error and display it here
// Try the fetch and parse again...
}
}
This requires that you hang on to the parser as an instance variable (self.parser), so that you can cancel it from the method you define. It also requires that your parser delegate keep track of whether or not the parser has finished (self.parsingDidComplete, can be defaulted to NO and set to YES in the delegate's parserDidEndDocument: method). This is to avoid aborting a successful parse. After this is done, all it takes is a simple
[self performSelector:#selector(parsingDidTimeout) withObject:nil afterDelay:30];
and thirty seconds later, your parsing-abort code will get called, and you can do whatever it is you need to do.
Second approach: using a timer
You could make this whole approach (arguably) simpler in the timeout method by using an NSTimer instead of the NSObject method call. That way, if the parser successfully finishes, you can simply invalidate the timer, allowing you to eliminate the if clause in the parsingDidTimeout method (and, as a result, also getting rid of the BOOL ivar). The timer initialization would look like:
NSTimer *timer = [NSTimer timerWithTimeInterval:30.0
target:self
selector:#selector(parsingDidTimeout)
userInfo:nil
repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
Doesn't answer your question direction, but you'd have complete control over the request and response cycle (as well as asynchronicity without additional threads) if you used NSURLConnection to download the data. That's what initWithContentsOfURL: is doing, under the covers.
Swift 3 example using NSTimer aka Timer
func startParseTimeoutTimer() {
Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { (_) in
if (self.busy) {
self.parser?.abortParsing()
self.parser = nil
print("Show UI as NOT busy; we aborted for timeout \(Thread.current.isMainThread)")
}
}
}