Read iOS Programming: The Big Nerd Ranch Guide, 3/e (Big Nerd Ranch Guides) Online
Authors: Aaron Hillegass,Joe Conway
Tags: #COM051370, #Big Nerd Ranch Guides, #iPhone / iPad Programming
A
BNRConnection
is the delegate for the
NSURLConnection
it manages, so it needs to implement the delegate methods for
NSURLConnection
that retrieve the data and report success or failure. First, implement the data collection method in
BNRConnection.m
.
Figure 28.9 BNRConnection flow
The
BNRConnection
will hold on to all of the data that returns from the web service. When that web service completes successfully, it must first parse that data into the
xmlRootObject
and then call the
completionBlock
(
Figure 28.9
). Finally, it needs to take itself out of the array of active connections so that it can be destroyed. Implement the following method in
BNRConnection.m
.
Remember that
connectionDidFinishLoading:
is called when the connection finishes successfully; so, the root object is delivered to the
completionBlock
, and no
NSError
is passed. If there is a problem with the connection, the opposite needs to occur: the completion block is called without the root object, and an error object is passed instead. In
BNRConnection.m
, implement the method that handles the connection failing.
Build and run the application. After a moment, you will see the
ListViewController
’s table view populate. If there is a problem, you will see an alert view.
You be wondering why
BNRConnection
’s
completionBlock
takes an argument of type
id
instead of say,
RSSChannel
. The answer is simple:
BNRConnection
doesn’t know anything about the type of its root object except that it receives
NSXMLParserDelegate
messages. Nor should it. This makes the
BNRConnection
usable in any situation that requires fetching XML data with
NSURLConnection
.
Now, at the end of the day, the changes we’ve made to
Nerdfeed
so far give us the exact same behavior as we had before. You might be wondering,
“
Why fix what ain’t broke?
”
Well, in the rest of this chapter and the next two, you will be adding features to
Nerdfeed
. Using a store object is going to make implementing those features a lot easier. (Also, the
BNRConnection
class is pretty handy – you can use that in any application. In fact, that very same class is in a number of applications that are currently on the App Store.)
Now that we have
BNRConnection
and a store object, adding new requests for the store to handle is really straight-forward. Let’s have the
BNRFeedStore
fetch the top songs from
iTunes
. First, we need to make a minor change to the
RSSChannel
and
RSSItem
classes because Apple’s RSS feed uses a different element name (
entry
) to identify items in their RSS feed. In
RSSChannel.m
, modify
parser:didStartElement:namespaceURI:qualifiedName:attributes:
to create an
RSSItem
when it encounters the
entry
element.
Then in
RSSItem.m
, have the
RSSItem
return control to the channel when it ends an
entry
element.
Now we will add another request that a controller can ask the
BNRFeedStore
to carry out. In
BNRFeedStore.h
, declare a new method.
The implementation of this method will be really easy now that we have the format of the store determined and the
BNRConnection
class ready to go. The two differences between
fetchTopSongs:withCompletion:
and
fetchRSSFeedWithCompletion:
are that
fetchTopSongs:withCompletion:
will take an argument supplied by the controller to determine how many songs to fetch and will access a different web service. Implement this method in
BNRFeedStore.m
.
Now we have a store object that returns two different RSS feeds, and the controller doesn’t have to know any of the details about how they are fetched. Let’s give the user a way to switch between the two feeds. In
ListViewController.h
, declare a new
enum
for the feed types and an instance variable to hold on to the current feed type.
In
ListViewController.m
, add a
UISegmentedControl
to the
navigationItem
that will change the
rssType
.
Then, in
ListViewController.m
, implement
changeType:
, which will be sent to the
ListViewController
when the segmented control changes.
Finally, modify
fetchEntries
in
ListViewController.m
to make the appropriate request to the store depending on the current
rssType
. To do this, move the completion block into a local variable, and then pass it to the right store request method. (The code that needs to be executed when either request finishes is the same.) This method will now look like this:
Build and run the application. When the application launches, the BNR forums feed will load as the default. Tap the
Apple
item in the segmented control, and the top ten songs on
iTunes
will appear. Simple stuff, huh? (Tapping on a row while looking at Apple’s RSS feed won’t show anything in the detail view controller, but you will fix this in the next section.)