Implementing Progress Indictor For NSURLConnectionDelegate protocol - objective-c

I'm trying to do some progress indication for when trying to upload and download a file.
Been reading and looks like this is the method that I need to use.
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
I'd like to read more about how that function works (i.e when is it called etc), but can't seem to find the reference documentation. I went to this URL but it does not say anything about that particular function.
https://developer.apple.com/library/mac/#documentation/Foundation/Reference/NSURLConnectionDelegate_Protocol/Reference/Reference.html%23//apple_ref/occ/intf/NSURLConnectionDelegate
Where can I read more about it?
Thank you,
Tee

NSURLConnection had an informal protocol for its delegate. That changed in iOS 5 (I think the same happened on OSX). They deprecated the methods declared in NSURLConnection and moved them into formal protocols NSURLConnectionDelegate and NSURLConnectionDataDelegate.
And now the fun part. They deprecated the methods, they even removed them from the NSURLConnection documentation but they did not document the new formal protocols.
Currently, only NSURLConnectionDelegate is documented. NSURLConnectionDataDelegate is not mentioned anywhere.
There are two ways how to find what the method does.
Look into the previous version of NSURLConnection docs (e.g. iOS 4.3). I would give you a link but I couldn't find it online. Maybe you have the library downloaded in your XCode
Press cmd-shift-o in Xcode, type NSURLConnectionDataDelegate and press enter. You have found the header and the methods have a description there:
connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:
is called during an upload operation to provide
progress feedback. Note that the values may
change in unexpected ways if the request needs to
be retransmitted.

Try AFNetworking It is beocming a popular replacement of ASIHTTPRequest, if you are concerned about support. Also it has a built in support for download progress. (See discussion on this link.) Here is a recent discussion of how to actually use it.
UPDATE
How do I track upload or download progress? (AFNetworking faq)
AFURLConnectionOperation provides the methods setUploadProgressBlock: and setDownloadProgressBlock:. Each method takes a single parameter, which is a block that will be executed periodically during the lifetime of the request. The block has no return type and takes 3 arguments: the number of bytes read or written for this callback, the total number of bytes read or written so far, and the total number of bytes expected to be read or written.
If you wanted to update a progress bar, you could set the respective progress block to set the progress amount to total number bytes read or written divided by the expected number, normalized between 0.0 and 1.0. UI updates based on this value will update asynchronously as the request is being made.

Related

Long delay with NSFileCoordinator coordinateWritingItemAtURL

I'm setting up NSFileCoordinator and NSFilePresenter in my app so I can do file IO from my AppleWatch app safely. There are some places in my code where I write to a file a couple of times in quick succession. This is a problem in and of itself and I'm working to correct it, but I'm noticing some weird behavior in the process.
I wrap my writes like this:
//In a class that implements NSFilePresenter:
NSFileCoordinator *coord = [[NSFileCoordinator alloc]initWithFilePresenter:self];
[coord coordinateWritingItemAtURL:self.presentedItemUrl options:0 error:nil byAccessor:^(NSURL *url)
{
//do my writing here using CFWriteStreamRef or NSOutputStream
}];
On the first write, the write block happens within 1 ms. But after that, there's about a 0.5 second delay between calling coordinateWritingItemAtURL and the write block being executed.
Is this expected behavior?
Some of the documentation for NSFileCoordinator and NSFilePresenter says to use prepareForReadingItemsAtURLs:writingItemsAtURLs:options:error:byAccessor: for batch operations, but it seems weird to get such a long delay when I don't batch.
Update: This happens with reading too.
Update 2: Here is an example project reproducing the problem.
Update 3: Using this API for coordination between an app and its extension is apparently a bad idea. But the question still stands.
Referring to File System Programming Guide , you can read following:
you might want to avoid incorporating changes directly from your file
presenter method. Instead, dispatch a block asynchronously to a
dispatch queue and process the changes at a later time. This lets you
process the changes at your app’s convenience without causing
unnecessary delays to the file coordinator that initiated the change.
Of course, when saving or relinquishing control of a file (such as in
the relinquishPresentedItemToReader:,
relinquishPresentedItemToWriter:, or
savePresentedItemChangesWithCompletionHandler: methods) you should
perform all necessary actions immediately and not defer them.
I think this is your case where you are defering actions.
Possible Solution:
Please read this well , to properly handle multiple successive writing operations , the relinquishPresentedItemToWriter , can do the job , same will work with reading file , relinquishPresentedItemToReader , supposing that multiple different objects are trying to read and write the same file.
P.S :
I dont know what your app does exactly , but i hope you have read this :
If you are implementing a document-based app, you do not need to
incorporate file presenter semantics into your NSDocument subclasses.
The NSDocument class already conforms to the NSFilePresenter protocol
and implements the appropriate methods. Thus, all of your documents
automatically register themselves as presenters of their corresponding
file and do things like save changes and track changes to the
document.
Is it possible to use options NSFileCoordinatorReadingImmediatelyAvailableMetadataOnly for reading and NSFileCoordinatorWritingContentIndependentMetadataOnly for writing in some cases? Looks like this iOS8 options can help you.

How to write an Objective-C REST API wrapper

I’m working of writing an Objective-C wrapper for a REST API. A lot of what I’m reading says not to use synchronous NSUrlConnection requests to avoid blocking the main thread. This makes sense, but I am wondering, what is the best way to make an API wrapper in Objective-C?
For example, we have an API method that takes a session ID and returns whether or not the session is valid. Ideally the wrapper method prototype would look like the following:
- (BOOL) sessionIsValid:(NSString *)sessionId;
So, that method could be called and the return value could be used to decide what to do next. But how would this work if the API call is asynchronous? It seems like the caller would need to set itself as the wrapper's delegate, make a request, and then process the response from the delegate method. Seems pretty ugly for such a simple API call. Is there a good way to achieve this?
Whether a session is valid or expired, should be an implementation detail of the underlying network layer. Thus, you would rarely have this method in a Objective-C API. Rather you would have an API that looks more like this:
typedef void (^completion_t)(id result, NSError* error);
- (void) fetchAllPostsWithUser:(ID)userID completion:(completion_t)completionHandler;
This is an asynchronous method. The call-site will be notified about the completion through calling the completion handler, which passes the result of the operation and possibly an error object. What result is actually, is entirely up to you: it may be an NSArray of custom objects of class Post or it may be JSON (either serialized or as objects), or whatever. In any case it must be clearly defined in the documentation.
Your "session problem" is part of the authentication scheme. In many cases, NSURLSession, respectively NSURLConnection can already handle authentication completely transparent for you. If not, there are a few delegate methods which can be overridden where you can tailor the behavior. A client (a developer using this API as a library) of that Objective-C API should never be concerned with such "abstract" and "obscure" notions like "session". He/she, knows just passwords, users, posts, etc. ;)
If you wanted to return a BOOL you would need to have already setup the session and cached the validity (expiry date) - which isn't always going to be possible. A delegate pattern is a good option. Don't forget that you can implement the delegate pattern using blocks (which give you the option of having multiple different delegates all using the API at the same time).

Is it OK to implement a protocol that's unavailable in my deployed OS version?

Say I'm writing an app to run on iOS7 and iOS6. I've a class that implements a protocol - a protocol only available in iOS7 (in this case, NSLayoutManagerDelegate).
Everything seems to work on iOS6 - my code that instantiates the class implementing the protocol is skipped on iOS6 - so it appears I'm good to go.
I was a little surprised not to see an error during app load though; apparently the loader is OK with me implementing a protocol that doesn't exist. Luckily for me!
Is there any Apple documentation that discusses this scenario? Is it safe? Any gotchas I should watch for?
No problem with that, a bit like implementing a method that is only called by the system for some version upwards.
At worst you can say that you have generated some code that takes up space somewhere (the "disk" if you can call it that on iOS and probably also the RAM) without being used on the older version(s), but that is minimal.
This all requires that the code is compiled with an SDK that includes the protocol in question - if conformance to the protocol is declared by using the <ProtocolName> construct and including the corresponding header. But that is kind of a given, since it won't compile otherwise.

Can I use blocks in asynchronous results with restkit?

--UPDATE: I've decided to give AFNetworking a try. Even though RestKit has a really nice object mapping functionality, the way the networking calls were designed have made some things difficult for us.
I'm hoping for some advice on how to organize my project that's using RestKit.
I have several REST calls from a repository class and its results get passed to controllers. For example I have a getProfile method in the repository class that is getting called from our browse view controller. The view controller is set as the delegate to the get profile calls while the repository class is set to the delegate for the restkit calls.
The problem is if the browse controller makes several get profile requests, it is difficult to distinguish which result should go to which delegate function since all the restkit calls share the same delegate method objectLoaderDidFinishLoading. I then have 4 delegates that I have to match the results of the 4 asynchronous restkit requests.
Is there any way I can use blocks so that I can pass a function to execute as the asnynrhounous result comes back so that I can assign a proper delegate? The block support that I saw allowed a block to be used before the request was sent out in rest kit but I am interested in using it for when the asynchronous result is returned.
The alternative of examining the results or setting user data and sleuthing what delegate goes with what asynchronous results seems unreliable and bulky.
You can solve your issues with disambiguating between your profile requests by using the userData opaque pointer on RKObjectLoader. That will allow you to hang any object you want on the request, which can then be used to help distinguish between multiple profile requests. Also, if those profile requests are going to different resourcePaths then you can just use the wasSentToResourcePath: method on RKObjectLoader to distinguish between them.
I just stumbled upon this question while trying to figure out this problem for my own REST interface. I'm glad I did, I'll probably use RestKit now.
I digress, back to your question. As you noted it doesn't seem like the block argument in the RKObjectManager is meant to be used this way. Instead, how about writing a class that implements RKObjectLoaderDelegate, takes in a block, and calls that block on any of the delegate calls.
Maybe something like this?
#interface MyObjectLoaderDelegate : NSObject <RKObjectLoaderDelegate>
#property (nonatomic, copy) void (^callback)(RKObjectLoader *loader, NSDictionary *objectDictionary, NSError *error)
- (id)initWithCallback:(void (^)(RKObjectLoader*, NSDictionary*, NSError*)aCallaback;
#end
And on any implemented delegate method you can execute the block. Since blocks retain scoped variables you can run code against the calling delegate.
Whatcha think?
I am not sure using blocks is the right way to solve your issue.
How about having a class GetProfile that implements RKObjectLoaderDelegate.
So you call the request from within here and set itself to be the delegate.
Then you have an objectLoader per request.
So in your view controller, each time you what GetProfile, you create an instance. And then when that instance messages your controller back (via delegates?) you know which it is.
I am just grappling with this issue as well, so am keen to hear feedback.
Switching over to AFNetworking seems to be the way to go... it was a much easier implementation for what I needed.

Call a macro every time any method is called - Objective C

I wrote a debug macro that prints to the console the passed-in string whenever the global kDebug flag == YES.
I need to print out the name of a method and its class name whenever any method is called.
That works fine when I painstakingly go through every method and write the name of the class and the method in a string.
Is there any special handler that gets called when any method in Objective-C is called, and if so, is there a way that I can somehow override it to call my debug macro?
The entire purpose of this is so that I don't have to go through every method in my code and hand-code the method signature in the debug macro call.
If you're looking for a method logging facility, rather than build your own, one is actually built into the Objective-C runtime.
You might want to read over the Objective-C section of Apple's Technote 2124:
Technical Note TN2124: Mac OS X Debugging Magic
I would also recommend reading over Dave Dribin's blog posting about using the runtime's facility for tracing messages. You can find that here: Tracing Objective-C messages - Dave Dribin's Blog. Dave notes a logObjCMessageSend function that gets called, which you could use to customize your logging behavior. It's a little tricky to use, but Dave gives the info necessary to successfully use it.
Take a look at Dtrace. Instruments provides a GUI interface. You can, say, provide a regex to match all the methods you want to log.
sounds like you were looking for the __PRETTY_FUNCTION__ macro... but the accepted answer is probably a better way to go.
I ended up with this code, after asking a similar question here How can I log names of each called class method in Objective-C?
- (BOOL)respondsToSelector:(SEL)aSelector {
if(aSelector){
NSLog(#"%#", NSStringFromSelector(aSelector));
}
return [super respondsToSelector:aSelector];
}