Background:
I am in the early stages of an an iPhone App and REST WebService product. Basically, I have a database on the a server and have written some REST APIs to access this database. I have a companion iphone app that will consume these REST APIs.
Questions:
What is the best approach to place the code for accessing the REST Apis? Should I create a separate subclass of NSObject and place the interface and implementation details there? I would like to reduce the amount of code duplication throughout the application in the various ViewControllers that would interact with the REST API.
For Example:
My app would start up and make a REST API call to determine the current state of local information on the device by comparing the value returned from the API vs local. Then I would initiate an update request from the API to refresh the local datastore.
Now if I have all of this logic in the start-up ViewController I have multiple calls using NSURLConnection which only has on delegate. I don't know how to make these separate calls in the same ViewController.
What are some approaches to solving this problem?
I generally create custom objects which use ASIHTTPRequest (using composition, not subclassing) which can be initialised with any required parameters, and use that to manage requests to the RESTful service. The custom object will provide a delegate protocol for handling success, failure and other custom notifications so that I can use this feedback to update the application UI while the request is performed asynchronously.
If you need to parse large amount of data returned from a request, make sure you launch a separate thread to do this, rather than doing it in your HTTP request success callback, otherwise this will keep the network activity spinner active longer than it actually should be.
If you need to manage multiple requests of the same type, you could add a "tag" property to your custom request, so that when your success/failure delegate response is called, you can easily identify which request it belongs to without having to keep an instance variable to the original request.
Related
So, I have 2 types of data, some needs to be persisted and some doesn't.
I'm thinking about where to put all my network related code, inside my UIViewControllers, where all the network request start from, or in a another layer.
What I had in mind is this:
Have a layer called NetworkManager.
NetworkManager is singerlton to all my web service calls.
For data that needs to be persistent and can be presented in a list, I would have network manager issues the request, save the response in my local core data DB, and have my UIViewController listen to that data using FetchResultsController.
But, there's many other types of requests. For example : login request, user info request, friendsNearBy, and so on… some don't have to be persistent in my db, and some don't fit the FRC architecture.
For these type of request, as far as I see, there are 2 ways of handling it:
1. Have another layer that separates between the ViewControllers and the NetworkManager.
Let's call it Mediator. The Mediator gets the dictionary(JSON) request from the networkManager, decides according to the app logic if there's anything else needs to be done with it, and then post a notification with appropriate name and data. If the mediator saves the UIViewController who issued the request, it can delegate the response directly to him instead of posting a notification.
The Flow would be like this:
MyUiViewController - > Mediator -> NetworkManger->Mediator-> PostNotification (or directly back to MyUiViewController)
Pros:
Decoupling
Nice structure and separation of concerns
Cons:
Harder to code
Sometimes harder to understand and debug.
2. Not having this 3 layered architecture, but instead having MyUiViewControllers, issue a network request with blocks. Meaning instead of the Mediator intercepting the response before MyUiViewController, just let MyUiViewController handle the response using blocks as he is the one that issues it.
Pros:
Simple and quick to code
Easy to understand
Cons:
Coupling of network code inside your controllers
I was hoping to get suggestions and comments about what's best from people's experience, or other/better way of doing this.
Have you got whats the best method already?
Here's what i do generally,
Have a NetworkManager which is not Singleton. Define a protocol with method OnSuccess,OnError. Implement this in your ViewController which initiates the network connection. Set the delegate on NetworkManager and let delegate be called when Asynchronous request is executed.
Use delegates instead of blocks as its easy to maintain.
This may not be best solution, but hopefully it gives you some pointers.
I recommend option 2 with a little bit of what you listed for option 1. In my apps I tend to have two distinct modes of operation that operate concurrently.
Automatic downloads:
App essential data is downloaded and saved directly to the database. It's initiated each time the app becomes active. As each request completes an NSNotification is sent out for any visible view controllers that may need to know about the new data.
For example, if I save player data I'll send a notification like "PlayerDataUpdated". When a view controller is visible it listens for notifications. When it's not visible it doesn't listen for notifications since any changes in to the database will be discovered during viewWillAppear.
User Initiated downloads:
For user-initiated network requests, such as pull to refresh, you should call the appropriate method on NetworkManager from the view controller that needs the updated data.
hi i am developing a sms App for my client. so far i have put down this plan in place.
1)The app keeps polling the server with an asynchronous request so that it does not interfere with the user interface.
2) for sending sms i am currently using synchronous request , depending on the reply from server i have do various things. i am showing the spinning circle and make the user wait until i get the response from server.
my client has problem with point 2.
The client says as soon as the send sms button is clicked it has to go back to the homescreen and should be able to navigate to any screen and do all other things that the app offers. i could have used async request , but i am not sure how to handle the responses from the server when i am on different view controller other than the one request is called from.
Can somebody help me on this.
Thank You.
The classic way of handling the response of an asynchronous action is either using delegation or notifications. Do not use a singleton. This breaks modularity and decoupling of different view controllers.
Roadmap of how to handle asynchronous actions
Register for the response of the asynchronous actions. This can be setting the delegate of the requesting object e.g. NSURLConnection to the view controller, which is typically self in this context. The othe possibility is that you register for the notification which is fired by the requesting object if things have happend e.g. when a download is finished or an error occurred.
Implement the delegate methods or the notifications to update your model and/or your user interface. Be aware that updating the UI has to happen on your main thread.
Start the asynchronous action. What happens in the background is that a separate thread is spawned or an operation is dispatched using GCD. These are implementation details and do not bother you.
Wait for the answer, which will result in one of your implemented methods to be executed which you then use to update what has changed.
Difference between notifications and delegates
The two differences between delegates and notifications is that delegate is a one-to-one connection between the delegate and the delegating object. Notifications are posted application wide and can be observed by as many objects as needed creating a one-to-many connection. Think about this as a broadcast. The second main difference is that delegation can be used to transfer information back from the delegate to the delegating object. Meaning that the delegating object asks the delegate for certain information. Typical example would be the data source of an UITableView. Notifications however are a one way street. The information flows from the posting object to the observing objects. This makes sense because think about the situation where you would have more than one observer and each would give feedback to the posting objects. Which one would be the right one?
In your case you would have to look up the delegate methods of the asynchronous HTTP request object and implement them accordingly.
Maybe you can try ASIHTTpRequest , It has Sync an Async request
If you using Async request , you can do anything after you press a button to do a request .
Check this
The solution depends on the response processing.... if you are just showing user that the sms sending is failed/successful than you can do it in any general utility class that shows alert.. but for this you have to create the singletone instance of your connection class so delegate(class itself) don't die when the response comes back.......
For this we need to keep track of currentViewController ....... we can do this by creating a reference ........ id currentViewController in appDelegate(with setter/getters).......... so it could be accessible in everywhere application........
its referred object should be changed each time when user changes the viewController.... that will help us to know on which viewController user is currently working.
than when the singeltone class of connection finished its response loading we can use this currentViewController with your desired viewController.
I am not sure how you are using different view controller....... pushing it/ presenting it or adding its view.....
I'm working on a new iPhone/iPod app that includes the need to do web services requests. I've found methods for doing these requests synchronously, or asynchronously by setting the controller as the delegate. What I'd really like to be able to do, though, is to create a single class that can handle all web requests for the whole application, and just create an instance of that class when I need to use it. That way, cookies and common pieces of code can be handled in one place, rather than all over the app.
So far the only thing I thought of that could accomplish what I'm trying to do is to create a new thread that handles the request synchronously within itself, then sends a message back to the calling controller once the request is complete. Is there a better way to accomplish what I'm trying to do?
Cookies are already a shared resource.
I would suggest reading the URL Loading System Overview to get an idea of how Apple set everything up. From what you describe, you want something very similar to how they have set up the system, maybe with a Singleton class for the connection. You can also look at ASIHTTPRequests which is a good wrapper around all of the connections stuff.
I would not suggest writing my own code here. Lots and lots of people have solved this problem for you.
I'm working on a largely navigation-based iPhone app that communicates with a REST API using OAuth, and I'd like to know how my classes should best communicate with each other. I've got multiple UITableViews, multiple UITableViewDataSources, an API class, and a view controller that handles authentication in a web view.
Here's how I have things structured now:
My UIApplicationDelegate owns an instance of the class that knows how to communicate with the REST API
I can ask the API class to call a REST method, and it returns with the data (it wraps ASIHTTPRequests to handle OAuth transparently, so it doesn't currently know which object asked for the data)
If the user isn't authenticated, I can ask the API class to initiate the OAuth process
The OAuth dialog can be presented, and the application granted access to the API on the user's behalf
The trouble I'm running into is that my UITableViewDataSources need to communicate with the API class to fetch their data, but authentication might need to happen first, which involves a modal authentication view presented by a view controller.
Would it be better to have each UITableViewDataSource model own its own instance of the API class, or should the API class be a singleton?
If each model owns an instance of the API class, how should it communicate to the view controller that authentication needs to happen?
If the API class is a singleton, how should it interact with multiple models and view controllers to present the authentication dialog? Delegates for each? Post NSNotifications?
Some other way I haven't thought of?
Really, I think the core of the problem is that I have one class that's primarily used for data fetching purposes, but it might need user interaction to do so successfully.
I typically use a singleton exactly in the way you describe and it works well. Here is how I would answer your questions.
Singleton
N/A. Use a singleton.
Notifications work well, but I tend to prefer to pass a delegate with each request and then keep a hold of it inside the singleton until the request has finished at which point I just call back to the delegate with a success or failure message. Notifications can get pretty messy if you have multiple view controllers that are live in your navigation stack all potentially listening and responding depending. I've seen that introduce some really weird bugs. If you're careful, notifications work just fine, but passing a delegate allows you to associate a specific delegate, typically the current view controller, with a specific request which is often ideal.
I think you're on the right track.
Not even sure if the title is correct, however, what I'm trying to do is use the standard NSURLConnection class to handle responses from calling my webservice. I am using the POST method to update a database and the GET method to retrieve rows from the database. The problem I have is that these 2 actions may occur simultaneously so that the methods to handle the request may step on each other. In other words in my "connection didReceiveData" method I have 2 paths through the code depending on whether I'm handling a response from a GET or POST request.
I keep track on which request in being processed by an instance variable called requestType. The problem is that since the requests are being executed simultaneously the instance variable is being changed from GET to POST before the GET completes (or vice-versa). My question is how do I maintain 2 separate requests in this scenario? Do I synchronize the requests? Is there a way for threads to work here? Do I create 2 separate objects for each of the requests and have the logic in "didRecieveData" query for which object is being processed? Any help would be much appreciated!!
Dealt with a similar issue in one of our apps. The solution involved creating a class that represents a webservice call, responsible for calling its own url, loading its own data, etc. The call class had a delegate that would handle parsing the responses (in our case, a web service controller). Wound up getting rather complicated, but prevented the issue of NSURLConnections stepping on each other.
Seems like you've created a messy problem by having a class that tries to do too many things. I would suggest taking one of the following three approaches:
1) Write two classes, one for updates and one for retrievals. Each class creates it's own private NSURLConnection object and acts as the delegate for the async notifications received from the NSURLConnection. The classes could possible share some utility parsing code or extend a base object that has that parsing code in it. But the key being that the code calling these classes would instantiate one of them, make the call, and then release it. This will keep your code cleaner and will insure that the event notifications don't get intermingled.
2) Create a single class that, depending on initialization, does either a post or a get with it's own private instance of NSURLConnection. When a call needs to be made, instantiate the class, get the results, and then release the class.
3) Write your connection handling classes so they use the synchronous NSURLConnection method and call that call that class in a background thread.
Either way, clean code and clear object orientation will prevent messy scenarios like the one you're describing.
Create separate objects that handle the calls. If you want to issue multiple requests at once I would strongly recommend looking at NSOperationQueue, and making these objects subclasses of NSOperation... much nicer way to deal with multiple background requests.
A good example is here:
http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/
The idea there is that you use the non-asyncronous web calls, in operations that are run on separate threads. You can still use asynch calls in NSOperation as well, but doing so is a little trickier and for simple calls you probably do not need to.