Best way to wait app Launch - objective-c

I have an app that requests from the server some data on xml type. Ok, it does ok.
But seems this action loads a little the app on launching.
TBXML *tbxml = nil;
tbxml = [[TBXML tbxmlWithURL:[NSURLURLWithString:#"http://www.someplace.com/test/test.xml"]] retain];
So, what i figured is make the app wait to launch completely to do this action. So, i've search for it, and find two ways.
applicationDidFinishLaunching;
awakeFromNib;
I dont know if this is the correct way to do this. So, im open to suggestions.
Thanks!

First, I would suggest you to put that XML loading code in a separate thread using NSOperationQueue or NSThread so that it won't block the main thread.
applicationDidFinishLaunching, IMHO, should be used to initialize your RootViewController, handle incoming push notifications, local notifications, etc. Use viewDidLoad in RootViewController for your purpose.

Related

Define a controller for NSDocument for document-based application

I'm not very sure how Document-Based Applications works.
I've created some actions for NSObject in the Mainmenu.xib. One of this is called when the user click on "File>new":
-(IBAction) newDocument:(id)sender{
Document* newDoc =[[Document alloc] init];
[[NSDocumentController sharedDocumentController]addDocument:newDoc];
[newDoc addWindowController: [[NSWindowController alloc] initWithWindowNibName:[newDoc windowNibName] owner:newDoc]];
[newDoc showWindows];
}
I've also this code inside the openDocument:(id) sender action that does the same but of course loading data to define the application workspace.
If I run the application it show a blank document without to call newDocument action. I don't know how to stop default blank document and to set newDocument: to be called.
Then if i do openDocument: too (so I've two documents, one blank and one not) and I do some operation on the second document it also replicate in the first blank one.
I've double check delegates, file owners, and also if the - (void)windowDidBecomeMain:(NSNotification *)notification return different pointers and all seem to be ok.
Probably I've not understood document based application work flow but I've read the Apple guide and other istructions. What do I miss?
An IBAction method is called, when the user did something. So this is not called from the system at app launch.
You can customize the behavior at app launch with -applicationShouldOpenUntitledFile: (NSApplicationDelegate) and – this is probably your next question – -applicationShouldHandleReopen:hasVisibleWindows: (NSApplicationDelegate). Changing the behavior in both cases is not recommended.
Looking to your action method, I see no reason, why you want to customize it.
A instance of your document class is created automatically.
You can create a window controller for it in your document subclass. This is documented.
Just let NSDocumentController do the work for you. What is the problem of the default behavior?
No. I thought to be confused instead the only problem was about releasing observer notification. When you call the close message for a NSDocument notification observers still persist. Working in ARC I miss this point.
So This is the solution at my issue. Thank you anyway.

AFNetworking Set runLoopModes?

AFNetworking default runLoopModes is NSRunLoopCommonModes.I want use NSDefaultRunLoopMode,and set it
operation.runLoopModes = [NSSet setWithObject:NSDefaultRunLoopMode];
But it doesn't work. when I scroll the scrollView,download task still running.
Anybody can help me? thanks.
So here we go, alternative solution, without hardcoded injection. Assuming you are using UIImageView+AFNetworking extension:
// user began scrolling
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[[UIImageView af_sharedImageRequestOperationQueue] setSuspended:YES];
}
// user released finger and scrolling animation is finished
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
[[UIImageView af_sharedImageRequestOperationQueue] setSuspended:NO];
}
Also check out Foursquare's solution, which relies on the same technique.
Recently I encountered similar question, while I was implementing images lazy loading in UITableView. User scrolling should have higher priority here.
Your direction is correct, the problem is in runloop modes. With UIImageView+AFNetworking extension, images are loaded with AFURLConnectionOperation, which is working on a separate network thread (see implementation), so NSURLConnections are running not on main thread.
To make the tasks stop when UITrackingRunLoopMode is active, you need to move networking code on main thread somehow.
Possible solutions:
Setup default runloop mode for your request operation.
AFImageRequestOperation *requestOperation = [[AFImageRequestOperation alloc] initWithRequest:urlRequest];
[requestOperation setRunLoopModes:[NSSet setWithObject:NSDefaultRunLoopMode]];
Put connection on main thread (that's ok, NSURLConnections are running their own threads): Find + (NSThread *)networkRequestThread and make it return [NSThread mainThread]. That might be not suitable with other situations, beware locks.
I am still not sure why AFNetworking is creating it's separate network thread. To process incoming data in background? If anybody have a guess, please reply.
Also see this question.

how to handle “sendDidFinish” in sharekit

I use sharekit with mail/twitter/facebook and I am really new to objective-c. sharekit works well and sends my images like it should.
in my app I have a screenshot function. I want the app to 'freeze' when a screenshot is taken, stopping to send any shake- or touch-event to the scene behind the sharekit-action.
in my screenshot-layer I have three buttons which call the shareItem-methods of their specified service, like
[SHKTwitter shareItem:item];
vereything works fine 'till here. but now when the sending is finished (or canceled or errored) I need the app to 'unfreeze', sharekit should tell my app that it is allowed to listen to any touch- or shake-action again.
I am sorry but I think I don't understand the concept of using the delegate here. I mean, is 'sendDidFinish' meant to be inside a delegate? and if so, how could I tell sharekit who is its delegate? or do I have to edit the send-service classes (like SHKItem or SHKFacebook) itself?
please don't downrate me for this question. I really want to get behind this mystery...
SHKTwitter inherit from SHKOAuthSharer, who inherit from SHKSharer. SHKSharer has a delegate protocol called "SharerDelegate".
So you can use an instance of SHKTwitter, then set it's delegate as :
shkTwitterInstance.shareDelegate = yourDelegateObject.
And implement the delegate method
- (void)sharerFinishedSending:(SHKSharer *)sharer;.
Try that.
EDIT (OTHER, AND MORE POPULAR, SOLUTION)
Also, you can suscribe your object to "SHKSendDidFinish" notification from SHKTwitter object.
[[NSNotificationCenter defaultCenter] addObserver:yourObject selector:#selector(theMethodthatYouWantToExecuteWhenTheNotificationIsRaised:) name:#"SHKSendDidFinish" object:shkTwitterObject];

uiprogressview update issue

I have two views, first one "A", has a button that trigger a web service to validate one code, if validation is successful, it performs a segue to the view "B".
In view B, I have this
- (bool) viewDidUpload
dispatch_async(kBgQueue, ^{
[self processContacts];
[self sendPost];
});
-(void) processContacts
//Process contact address
-(void) sendPost
//Process web services call
//If web service call is OK, call [self updateBar]
[self performSelectorOnMainThread:#selector(updateBar)
withObject:nil waitUntilDone:YES];
UPDATED: I implemented GDC to send sendPost and processContacts in the background, then sendPost method has the updateBar call performed using performSelectorOnMainThread:, the problem is that the execution doesn't enter in this method and it finishes without updating the bar. sendPost and processContacts now run in the background, but I don't know how to perform updateBar in the main every time a valid connection is done, and then return to the background and perform rest of connections and again.
Many thanks
You should perform all calculations and communications in background thread. Then do updates on GUI stuff (like progress bar) in your main thread.
Take a look at GCD. It is really easy to use and will solve your problem I'm sure.
So seems that you are using internet and best way for me to do so is using the Git library of ASIHTTPRequest, read it and download it then use it, it's very useful, enjoy:
http://allseeing-i.com/ASIHTTPRequest/

how can we use combination of NSThread and NSNotification?

I am doing an application where images from the user are taken all together and saved in NSMutableArray.
As soon as even one image has been start coming, I need to upload images to server one by one though images are taken together
I am using [NSThread detachNewThreadSelector:#selector(uploading:) toTarget:self withObject:imagearray]; to upload images one by one. I need to show progressview to user as images are being uploaded one by one.
How do I notify after one image has been uploaded?
Or is there any other scenario that is useful for this more than NSThread+NSNotification?
I sugest to use something similar to "delegate" paradigm but thinking on threads instead of objects. So the uploading thread delegates on main thread as it is the one to make user interface changes.
For example, the uploading thread can send messages for partial upload progress
[self performSelectorOnMainThread:#selector(uploadProgression:)
withObject:foo waitUntilDone:NO]
or for each complete upload finished
[self performSelectorOnMainThread:#selector(uploadDidEnd:) withObject:foo
waitUntilDone:YES]
I suppose that you have not to stop uploading for updating partial progress in progessView but you need to wait when upload ends so not to duplicate uploading threads launching a new upload.
You should use notifications in case you don't know how many listeners it is out there and you just post notification about something. In your case you probably have only one view controller, so there is no need to use notifications so just create some protocol for the delegate and implement it in your view controller. If you need to update your UI, then you should also invoke all delegate methods using performSelectorOnMainThread.