Merge lp:~rockstar/ubuntuone-ios-music/dial-down into lp:~ubuntuone-ios-client-team/ubuntuone-ios-music/moriarty
- dial-down
- Merge into moriarty
Proposed by
Paul Hummer
Status: | Merged |
---|---|
Merge reported by: | Paul Hummer |
Merged at revision: | not available |
Proposed branch: | lp:~rockstar/ubuntuone-ios-music/dial-down |
Merge into: | lp:~ubuntuone-ios-client-team/ubuntuone-ios-music/moriarty |
Prerequisite: | lp:~rockstar/ubuntuone-ios-music/coredata |
Diff against target: |
1432 lines (+558/-320) 24 files modified
Music/AppDelegate.m (+6/-31) Music/Categories/RKRequest+Plaintext.h (+0/-13) Music/Categories/RKRequest+Plaintext.m (+0/-55) Music/Models/Album.h (+2/-0) Music/Models/Album.m (+28/-11) Music/Models/Artist.m (+9/-8) Music/Models/Playlist.m (+9/-8) Music/Models/Song.m (+74/-32) Music/Models/UOModel.h (+2/-2) Music/Models/UOModel.m (+8/-3) Music/Utilities/UOWebServiceController.h (+39/-0) Music/Utilities/UOWebServiceController.m (+204/-0) Music/View Controllers/AlbumViewController.h (+1/-1) Music/View Controllers/AlbumViewController.m (+52/-25) Music/View Controllers/AlbumsViewController.m (+9/-8) Music/View Controllers/ArtistViewController.h (+1/-1) Music/View Controllers/ArtistViewController.m (+58/-31) Music/View Controllers/ArtistsViewController.m (+10/-10) Music/View Controllers/PlaylistsViewController.m (+8/-7) Music/View Controllers/SongsViewController.m (+6/-5) Music/View Controllers/UOIndexedViewController.h (+2/-2) Music/View Controllers/UOIndexedViewController.m (+21/-37) U1Music.xcodeproj/project.pbxproj (+6/-21) U1Music_Prefix.pch (+3/-9) |
To merge this branch: | bzr merge lp:~rockstar/ubuntuone-ios-music/dial-down |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michał Karnicki (community) | Approve | ||
Review via email: mp+141684@code.launchpad.net |
Commit message
Description of the change
This branch adds the core data support to the ancilliary views that are dialed
down to through selection. It also warranted an upgrade to Core Data so that
we could only fetch when absolutely necessary. I *think* this is likely to be
the last big branch. Sorry it's so big.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'Music/AppDelegate.m' | |||
2 | --- Music/AppDelegate.m 2013-01-02 23:49:22 +0000 | |||
3 | +++ Music/AppDelegate.m 2013-01-02 23:49:23 +0000 | |||
4 | @@ -37,7 +37,6 @@ | |||
5 | 37 | @synthesize storyboard = _storyboard; | 37 | @synthesize storyboard = _storyboard; |
6 | 38 | 38 | ||
7 | 39 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { | 39 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { |
8 | 40 | [self initRestKit]; | ||
9 | 41 | 40 | ||
10 | 42 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; | 41 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; |
11 | 43 | 42 | ||
12 | @@ -164,6 +163,12 @@ | |||
13 | 164 | return _persistentStoreCoordinator; | 163 | return _persistentStoreCoordinator; |
14 | 165 | } | 164 | } |
15 | 166 | 165 | ||
16 | 166 | #pragma mark - Convenience methods | ||
17 | 167 | |||
18 | 168 | + (AppDelegate *)delegate { | ||
19 | 169 | return (AppDelegate *)[UIApplication sharedApplication].delegate; | ||
20 | 170 | } | ||
21 | 171 | |||
22 | 167 | #pragma mark - Application's Documents directory | 172 | #pragma mark - Application's Documents directory |
23 | 168 | 173 | ||
24 | 169 | // Returns the URL to the application's Documents directory. | 174 | // Returns the URL to the application's Documents directory. |
25 | @@ -180,34 +185,4 @@ | |||
26 | 180 | [self.window makeKeyAndVisible]; | 185 | [self.window makeKeyAndVisible]; |
27 | 181 | } | 186 | } |
28 | 182 | 187 | ||
29 | 183 | #pragma mark - Convenience methods | ||
30 | 184 | |||
31 | 185 | + (AppDelegate *)delegate { | ||
32 | 186 | return (AppDelegate *)[UIApplication sharedApplication].delegate; | ||
33 | 187 | } | ||
34 | 188 | |||
35 | 189 | #pragma mark - Private methods | ||
36 | 190 | |||
37 | 191 | - (void)initRestKit { | ||
38 | 192 | NSDictionary *credentials = [[UOAuthManager sharedAuthManager] oauthCredentials]; | ||
39 | 193 | RKURL *baseURL = [RKURL URLWithBaseURLString:@"https://one.ubuntu.com/api/music/v2"]; | ||
40 | 194 | |||
41 | 195 | RKObjectManager *objectManager = [RKObjectManager objectManagerWithBaseURL:baseURL]; | ||
42 | 196 | objectManager.client.baseURL = baseURL; | ||
43 | 197 | objectManager.client.OAuth1ConsumerKey = [credentials objectForKey:UOOAuthConsumerKey]; | ||
44 | 198 | objectManager.client.OAuth1ConsumerSecret = [credentials objectForKey:UOOAuthConsumerSecret]; | ||
45 | 199 | objectManager.client.OAuth1AccessToken = [credentials objectForKey:UOOAuthToken]; | ||
46 | 200 | objectManager.client.OAuth1AccessTokenSecret = [credentials objectForKey:UOOAuthTokenSecret]; | ||
47 | 201 | objectManager.client.authenticationType = RKRequestAuthenticationTypeOAuth1; | ||
48 | 202 | static NSString *DatabaseName = @"UOMusic.sql"; | ||
49 | 203 | |||
50 | 204 | RKManagedObjectStore *objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:DatabaseName]; | ||
51 | 205 | objectManager.objectStore = objectStore; | ||
52 | 206 | |||
53 | 207 | [Album registerMapping]; | ||
54 | 208 | [Artist registerMapping]; | ||
55 | 209 | [Playlist registerMapping]; | ||
56 | 210 | [Song registerMapping]; | ||
57 | 211 | } | ||
58 | 212 | |||
59 | 213 | @end | 188 | @end |
60 | 214 | 189 | ||
61 | === removed file 'Music/Categories/RKRequest+Plaintext.h' | |||
62 | --- Music/Categories/RKRequest+Plaintext.h 2012-12-07 22:39:22 +0000 | |||
63 | +++ Music/Categories/RKRequest+Plaintext.h 1970-01-01 00:00:00 +0000 | |||
64 | @@ -1,13 +0,0 @@ | |||
65 | 1 | // | ||
66 | 2 | // RKRequest+Plaintext.h | ||
67 | 3 | // U1Music | ||
68 | 4 | // | ||
69 | 5 | // Created by Paul Hummer on 10/5/12. | ||
70 | 6 | // Copyright (c) 2012 Canonical. All rights reserved. | ||
71 | 7 | // | ||
72 | 8 | |||
73 | 9 | #import <RestKit/RestKit.h> | ||
74 | 10 | |||
75 | 11 | @interface RKRequest (Plaintext) | ||
76 | 12 | |||
77 | 13 | @end | ||
78 | 14 | 0 | ||
79 | === removed file 'Music/Categories/RKRequest+Plaintext.m' | |||
80 | --- Music/Categories/RKRequest+Plaintext.m 2012-12-07 22:39:22 +0000 | |||
81 | +++ Music/Categories/RKRequest+Plaintext.m 1970-01-01 00:00:00 +0000 | |||
82 | @@ -1,55 +0,0 @@ | |||
83 | 1 | // | ||
84 | 2 | // RKRequest+Plaintext.m | ||
85 | 3 | // U1Music | ||
86 | 4 | // | ||
87 | 5 | // Created by Paul Hummer on 10/5/12. | ||
88 | 6 | // Copyright (c) 2012 Canonical. All rights reserved. | ||
89 | 7 | // | ||
90 | 8 | |||
91 | 9 | #import <RestKit/RestKit.h> | ||
92 | 10 | #import "RKRequest+Plaintext.h" | ||
93 | 11 | #import "UOAuthManager.h" | ||
94 | 12 | |||
95 | 13 | @implementation RKRequest (Plaintext) | ||
96 | 14 | |||
97 | 15 | /* rockstar: 5 Oct 2012 - This is as copy/pasted as I could possibly get. It's a hack, and | ||
98 | 16 | I'm so very very sorry. The fact remains that Ubuntu One doesn't currently support the | ||
99 | 17 | HMAC-SHA1 signature method, and RestKit's oauth library doesn't support Plaintext. I'm going | ||
100 | 18 | to work towards getting Plaintext support into RestKit. | ||
101 | 19 | */ | ||
102 | 20 | - (void)addHeadersToRequest | ||
103 | 21 | { | ||
104 | 22 | NSString *header = nil; | ||
105 | 23 | for (header in self.additionalHTTPHeaders) { | ||
106 | 24 | [self.URLRequest setValue:[self.additionalHTTPHeaders valueForKey:header] forHTTPHeaderField:header]; | ||
107 | 25 | } | ||
108 | 26 | |||
109 | 27 | [self.URLRequest setValue:nil forHTTPHeaderField:@"Content-Length"]; | ||
110 | 28 | |||
111 | 29 | /* This is the specific part that needs to be overridden. The OAuth2 stuff has been removed, | ||
112 | 30 | and since we know that we're using OAuth, we don't check against it. | ||
113 | 31 | */ | ||
114 | 32 | NSURLRequest *echo = nil; | ||
115 | 33 | |||
116 | 34 | // use the suitable parameters dict | ||
117 | 35 | NSDictionary *parameters = nil; | ||
118 | 36 | if ([self.params isKindOfClass:[RKParams class]]) | ||
119 | 37 | parameters = [(RKParams *)self.params dictionaryOfPlainTextParams]; | ||
120 | 38 | else | ||
121 | 39 | parameters = [self.URL queryParameters]; | ||
122 | 40 | |||
123 | 41 | echo = [UOAuthManager oauthRequestForPath:[self.URL path]]; | ||
124 | 42 | [self.URLRequest setValue:[echo valueForHTTPHeaderField:@"Authorization"] forHTTPHeaderField:@"Authorization"]; | ||
125 | 43 | [self.URLRequest setValue:[echo valueForHTTPHeaderField:@"Accept-Encoding"] forHTTPHeaderField:@"Accept-Encoding"]; | ||
126 | 44 | [self.URLRequest setValue:[echo valueForHTTPHeaderField:@"User-Agent"] forHTTPHeaderField:@"User-Agent"]; | ||
127 | 45 | |||
128 | 46 | if (self.cachePolicy & RKRequestCachePolicyEtag) { | ||
129 | 47 | NSString *etag = [self.cache etagForRequest:self]; | ||
130 | 48 | if (etag) { | ||
131 | 49 | RKLogTrace(@"Setting If-None-Match header to '%@'", etag); | ||
132 | 50 | [self.URLRequest setValue:etag forHTTPHeaderField:@"If-None-Match"]; | ||
133 | 51 | } | ||
134 | 52 | } | ||
135 | 53 | } | ||
136 | 54 | |||
137 | 55 | @end | ||
138 | 56 | 0 | ||
139 | === modified file 'Music/Models/Album.h' | |||
140 | --- Music/Models/Album.h 2013-01-02 23:49:22 +0000 | |||
141 | +++ Music/Models/Album.h 2013-01-02 23:49:23 +0000 | |||
142 | @@ -24,4 +24,6 @@ | |||
143 | 24 | 24 | ||
144 | 25 | @property (nonatomic, retain) NSString *artistId; | 25 | @property (nonatomic, retain) NSString *artistId; |
145 | 26 | @property (nonatomic, retain, readonly) Artist *artist; | 26 | @property (nonatomic, retain, readonly) Artist *artist; |
146 | 27 | |||
147 | 28 | @property (nonatomic, retain) NSSet *songs; | ||
148 | 27 | @end | 29 | @end |
149 | 28 | 30 | ||
150 | === modified file 'Music/Models/Album.m' | |||
151 | --- Music/Models/Album.m 2013-01-02 23:49:22 +0000 | |||
152 | +++ Music/Models/Album.m 2013-01-02 23:49:23 +0000 | |||
153 | @@ -8,6 +8,7 @@ | |||
154 | 8 | 8 | ||
155 | 9 | #import "Album.h" | 9 | #import "Album.h" |
156 | 10 | #import <RestKit/RestKit.h> | 10 | #import <RestKit/RestKit.h> |
157 | 11 | #import <RestKit/CoreData.h> | ||
158 | 11 | #import "Artist.h" | 12 | #import "Artist.h" |
159 | 12 | #import "NSString+Extras.h" | 13 | #import "NSString+Extras.h" |
160 | 13 | 14 | ||
161 | @@ -24,18 +25,21 @@ | |||
162 | 24 | @synthesize artistId; | 25 | @synthesize artistId; |
163 | 25 | @dynamic artist; | 26 | @dynamic artist; |
164 | 26 | 27 | ||
166 | 27 | + (RKManagedObjectMapping *)objectMapping { | 28 | @dynamic songs; |
167 | 29 | |||
168 | 30 | + (RKEntityMapping *)objectMapping { | ||
169 | 28 | RKObjectManager *manager = [RKObjectManager sharedManager]; | 31 | RKObjectManager *manager = [RKObjectManager sharedManager]; |
170 | 29 | 32 | ||
180 | 30 | RKManagedObjectMapping *mapping = [RKManagedObjectMapping mappingForClass:[self class] inManagedObjectStore:manager.objectStore]; | 33 | RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Album" inManagedObjectStore:manager.managedObjectStore]; |
181 | 31 | [mapping mapKeyPath:@"id" toAttribute:@"albumId"]; | 34 | [mapping setIdentificationAttributes:@[@"albumId"]]; |
182 | 32 | [mapping mapKeyPath:@"album_url" toAttribute:@"url"]; | 35 | [mapping addAttributeMappingsFromDictionary:@{ |
183 | 33 | [mapping mapKeyPath:@"cover_art" toAttribute:@"art"]; | 36 | @"id": @"albumId", |
184 | 34 | [mapping mapKeyPath:@"album_art_url" toAttribute:@"artUrl"]; | 37 | @"album_url": @"url", |
185 | 35 | [mapping mapKeyPath:@"title" toAttribute:@"title"]; | 38 | @"cover_art": @"art", |
186 | 36 | [mapping mapKeyPath:@"artist_id" toAttribute:@"artistId"]; | 39 | @"album_art_url": @"artUrl", |
187 | 37 | 40 | @"title": @"title", | |
188 | 38 | mapping.primaryKeyAttribute = @"albumId"; | 41 | @"artist_id": @"artistId" |
189 | 42 | }]; | ||
190 | 39 | 43 | ||
191 | 40 | return mapping; | 44 | return mapping; |
192 | 41 | } | 45 | } |
193 | @@ -50,7 +54,20 @@ | |||
194 | 50 | } | 54 | } |
195 | 51 | 55 | ||
196 | 52 | - (void)setArtistId:(NSString *)_artistId { | 56 | - (void)setArtistId:(NSString *)_artistId { |
198 | 53 | Artist *_artist = [Artist findByPrimaryKey:_artistId inContext:self.managedObjectContext]; | 57 | NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; |
199 | 58 | NSEntityDescription *entity = [NSEntityDescription entityForName:@"Artist" inManagedObjectContext:self.managedObjectContext]; | ||
200 | 59 | [fetchRequest setEntity:entity]; | ||
201 | 60 | |||
202 | 61 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(artistId = %@)", _artistId]; | ||
203 | 62 | [fetchRequest setPredicate:predicate]; | ||
204 | 63 | |||
205 | 64 | NSError *error; | ||
206 | 65 | NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; | ||
207 | 66 | if (error || [results count] != 1) { | ||
208 | 67 | abort(); | ||
209 | 68 | } | ||
210 | 69 | |||
211 | 70 | Artist *_artist = [results objectAtIndex:0]; | ||
212 | 54 | [self setPrimitiveValue:_artist forKey:@"artist"]; | 71 | [self setPrimitiveValue:_artist forKey:@"artist"]; |
213 | 55 | } | 72 | } |
214 | 56 | 73 | ||
215 | 57 | 74 | ||
216 | === modified file 'Music/Models/Artist.m' | |||
217 | --- Music/Models/Artist.m 2013-01-02 23:49:22 +0000 | |||
218 | +++ Music/Models/Artist.m 2013-01-02 23:49:23 +0000 | |||
219 | @@ -20,16 +20,17 @@ | |||
220 | 20 | 20 | ||
221 | 21 | @synthesize index; | 21 | @synthesize index; |
222 | 22 | 22 | ||
224 | 23 | + (RKManagedObjectMapping *)objectMapping { | 23 | + (RKEntityMapping *)objectMapping { |
225 | 24 | RKObjectManager *manager = [RKObjectManager sharedManager]; | 24 | RKObjectManager *manager = [RKObjectManager sharedManager]; |
226 | 25 | 25 | ||
234 | 26 | RKManagedObjectMapping *mapping = [RKManagedObjectMapping mappingForClass:[self class] inManagedObjectStore:manager.objectStore]; | 26 | RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Artist" inManagedObjectStore:manager.managedObjectStore]; |
235 | 27 | [mapping mapKeyPath:@"id" toAttribute:@"artistId"]; | 27 | [mapping setIdentificationAttributes:@[@"artistId"]]; |
236 | 28 | [mapping mapKeyPath:@"artist" toAttribute:@"name"]; | 28 | [mapping addAttributeMappingsFromDictionary:@{ |
237 | 29 | [mapping mapKeyPath:@"artist_url" toAttribute:@"url"]; | 29 | @"id" : @"artistId", |
238 | 30 | [mapping mapKeyPath:@"artist_art_url" toAttribute:@"artUrl"]; | 30 | @"artist": @"name", |
239 | 31 | 31 | @"artist_url": @"url", | |
240 | 32 | mapping.primaryKeyAttribute = @"artistId"; | 32 | @"artist_art_url": @"artUrl", |
241 | 33 | }]; | ||
242 | 33 | return mapping; | 34 | return mapping; |
243 | 34 | } | 35 | } |
244 | 35 | 36 | ||
245 | 36 | 37 | ||
246 | === modified file 'Music/Models/Playlist.m' | |||
247 | --- Music/Models/Playlist.m 2013-01-02 23:49:22 +0000 | |||
248 | +++ Music/Models/Playlist.m 2013-01-02 23:49:23 +0000 | |||
249 | @@ -19,16 +19,17 @@ | |||
250 | 19 | 19 | ||
251 | 20 | @synthesize index; | 20 | @synthesize index; |
252 | 21 | 21 | ||
254 | 22 | + (RKManagedObjectMapping *)objectMapping { | 22 | + (RKEntityMapping *)objectMapping { |
255 | 23 | RKObjectManager *manager = [RKObjectManager sharedManager]; | 23 | RKObjectManager *manager = [RKObjectManager sharedManager]; |
256 | 24 | 24 | ||
264 | 25 | RKManagedObjectMapping *mapping = [RKManagedObjectMapping mappingForClass:[self class] inManagedObjectStore:manager.objectStore]; | 25 | RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Playlist" inManagedObjectStore:manager.managedObjectStore]; |
265 | 26 | [mapping mapKeyPath:@"id" toAttribute:@"playlistId"]; | 26 | [mapping setIdentificationAttributes:@[@"playlistId"]]; |
266 | 27 | [mapping mapKeyPath:@"playlist_url" toAttribute:@"url"]; | 27 | [mapping addAttributeMappingsFromDictionary:@{ |
267 | 28 | [mapping mapKeyPath:@"name" toAttribute:@"title"]; | 28 | @"id": @"playlistId", |
268 | 29 | [mapping mapKeyPath:@"song_count" toAttribute:@"songCount"]; | 29 | @"playlist_url": @"url", |
269 | 30 | 30 | @"name": @"title", | |
270 | 31 | mapping.primaryKeyAttribute = @"playlistId"; | 31 | @"song_count": @"songCount", |
271 | 32 | }]; | ||
272 | 32 | return mapping; | 33 | return mapping; |
273 | 33 | } | 34 | } |
274 | 34 | 35 | ||
275 | 35 | 36 | ||
276 | === modified file 'Music/Models/Song.m' | |||
277 | --- Music/Models/Song.m 2013-01-02 23:49:22 +0000 | |||
278 | +++ Music/Models/Song.m 2013-01-02 23:49:23 +0000 | |||
279 | @@ -33,35 +33,35 @@ | |||
280 | 33 | 33 | ||
281 | 34 | @synthesize index; | 34 | @synthesize index; |
282 | 35 | 35 | ||
286 | 36 | @synthesize album = _album; | 36 | @dynamic album; |
287 | 37 | @synthesize artist = _artist; | 37 | @dynamic artist; |
288 | 38 | @synthesize albumArtist = _albumArtist; | 38 | @dynamic albumArtist; |
289 | 39 | 39 | ||
291 | 40 | + (RKManagedObjectMapping *)objectMapping { | 40 | + (RKEntityMapping *)objectMapping { |
292 | 41 | RKObjectManager *manager = [RKObjectManager sharedManager]; | 41 | RKObjectManager *manager = [RKObjectManager sharedManager]; |
293 | 42 | 42 | ||
316 | 43 | RKManagedObjectMapping *mapping = [RKManagedObjectMapping mappingForClass:[self class] inManagedObjectStore:manager.objectStore]; | 43 | RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"Song" inManagedObjectStore:manager.managedObjectStore]; |
317 | 44 | 44 | [mapping setIdentificationAttributes:@[@"songId"]]; | |
318 | 45 | [mapping mapKeyPath:@"song_url" toAttribute:@"url"]; | 45 | [mapping addAttributeMappingsFromDictionary:@{ |
319 | 46 | [mapping mapKeyPath:@"song_art_url" toAttribute:@"artUrl"]; | 46 | @"song_url": @"url", |
320 | 47 | [mapping mapKeyPath:@"suffix" toAttribute:@"suffix"]; | 47 | @"song_art_url": @"artUrl", |
321 | 48 | [mapping mapKeyPath:@"track" toAttribute:@"track"]; | 48 | @"suffix": @"suffix", |
322 | 49 | [mapping mapKeyPath:@"title" toAttribute:@"title"]; | 49 | @"track": @"track", |
323 | 50 | [mapping mapKeyPath:@"album_artist_id" toAttribute:@"albumArtistId"]; | 50 | @"title": @"title", |
324 | 51 | [mapping mapKeyPath:@"bit_rate" toAttribute:@"bitRate"]; | 51 | @"album_artist_id": @"albumArtistId", |
325 | 52 | [mapping mapKeyPath:@"id" toAttribute:@"songId"]; | 52 | @"bit_rate": @"bitRate", |
326 | 53 | [mapping mapKeyPath:@"duration" toAttribute:@"duration"]; | 53 | @"id": @"songId", |
327 | 54 | [mapping mapKeyPath:@"disc_number" toAttribute:@"discNumber"]; | 54 | @"duration": @"duration", |
328 | 55 | [mapping mapKeyPath:@"song_stream_url" toAttribute:@"streamUrl"]; | 55 | @"disc_number": @"discNumber", |
329 | 56 | [mapping mapKeyPath:@"content_type" toAttribute:@"contentType"]; | 56 | @"song_stream_url": @"streamUrl", |
330 | 57 | [mapping mapKeyPath:@"year" toAttribute:@"year"]; | 57 | @"content_type": @"contentType", |
331 | 58 | [mapping mapKeyPath:@"genre" toAttribute:@"genre"]; | 58 | @"year": @"year", |
332 | 59 | [mapping mapKeyPath:@"path" toAttribute:@"path"]; | 59 | @"genre": @"genre", |
333 | 60 | [mapping mapKeyPath:@"artist_id" toAttribute:@"artistId"]; | 60 | @"path": @"path", |
334 | 61 | [mapping mapKeyPath:@"album_id" toAttribute:@"albumId"]; | 61 | @"artist_id": @"artistId", |
335 | 62 | [mapping mapKeyPath:@"size" toAttribute:@"size"]; | 62 | @"album_id": @"albumId", |
336 | 63 | 63 | @"size": @"size" | |
337 | 64 | mapping.primaryKeyAttribute = @"songId"; | 64 | }]; |
338 | 65 | return mapping; | 65 | return mapping; |
339 | 66 | } | 66 | } |
340 | 67 | 67 | ||
341 | @@ -81,24 +81,66 @@ | |||
342 | 81 | return _index; | 81 | return _index; |
343 | 82 | } | 82 | } |
344 | 83 | 83 | ||
347 | 84 | - (void)setArtistId:(NSString *)artistId { | 84 | - (void)setArtistId:(NSString *)_artistId { |
348 | 85 | _artist = [Artist findByPrimaryKey:artistId inContext:self.managedObjectContext]; | 85 | NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; |
349 | 86 | NSEntityDescription *entity = [NSEntityDescription entityForName:@"Artist" inManagedObjectContext:self.managedObjectContext]; | ||
350 | 87 | [fetchRequest setEntity:entity]; | ||
351 | 88 | |||
352 | 89 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(artistId = %@)", _artistId]; | ||
353 | 90 | [fetchRequest setPredicate:predicate]; | ||
354 | 91 | |||
355 | 92 | NSError *error; | ||
356 | 93 | NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; | ||
357 | 94 | if (error || [results count] != 1) { | ||
358 | 95 | abort(); | ||
359 | 96 | } | ||
360 | 97 | |||
361 | 98 | Artist *_artist = [results objectAtIndex:0]; | ||
362 | 99 | [self setPrimitiveValue:_artist forKey:@"artist"]; | ||
363 | 86 | } | 100 | } |
364 | 87 | 101 | ||
365 | 88 | - (NSString *)artistId { | 102 | - (NSString *)artistId { |
366 | 89 | return self.artist.artistId; | 103 | return self.artist.artistId; |
367 | 90 | } | 104 | } |
368 | 91 | 105 | ||
371 | 92 | - (void)setAlbumId:(NSString *)albumId { | 106 | - (void)setAlbumId:(NSString *)_albumId { |
372 | 93 | _album = [Album findByPrimaryKey:albumId inContext:self.managedObjectContext]; | 107 | NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; |
373 | 108 | NSEntityDescription *entity = [NSEntityDescription entityForName:@"Album" inManagedObjectContext:self.managedObjectContext]; | ||
374 | 109 | [fetchRequest setEntity:entity]; | ||
375 | 110 | |||
376 | 111 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(albumId = %@)", _albumId]; | ||
377 | 112 | [fetchRequest setPredicate:predicate]; | ||
378 | 113 | |||
379 | 114 | NSError *error; | ||
380 | 115 | NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; | ||
381 | 116 | if (error || [results count] != 1) { | ||
382 | 117 | abort(); | ||
383 | 118 | } | ||
384 | 119 | |||
385 | 120 | Artist *_artist = [results objectAtIndex:0]; | ||
386 | 121 | [self setPrimitiveValue:_artist forKey:@"album"]; | ||
387 | 94 | } | 122 | } |
388 | 95 | 123 | ||
389 | 96 | - (NSString *)albumId { | 124 | - (NSString *)albumId { |
390 | 97 | return self.album.albumId; | 125 | return self.album.albumId; |
391 | 98 | } | 126 | } |
392 | 99 | 127 | ||
395 | 100 | - (void)setAlbumArtistId:(NSString *)albumArtistId { | 128 | - (void)setAlbumArtistId:(NSString *)_albumArtistId { |
396 | 101 | _albumArtist = [Artist findByPrimaryKey:albumArtistId inContext:self.managedObjectContext]; | 129 | NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; |
397 | 130 | NSEntityDescription *entity = [NSEntityDescription entityForName:@"Artist" inManagedObjectContext:self.managedObjectContext]; | ||
398 | 131 | [fetchRequest setEntity:entity]; | ||
399 | 132 | |||
400 | 133 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(artistId = %@)", _albumArtistId]; | ||
401 | 134 | [fetchRequest setPredicate:predicate]; | ||
402 | 135 | |||
403 | 136 | NSError *error; | ||
404 | 137 | NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; | ||
405 | 138 | if (error || [results count] != 1) { | ||
406 | 139 | abort(); | ||
407 | 140 | } | ||
408 | 141 | |||
409 | 142 | Artist *_artist = [results objectAtIndex:0]; | ||
410 | 143 | [self setPrimitiveValue:_artist forKey:@"albumArtist"]; | ||
411 | 102 | } | 144 | } |
412 | 103 | 145 | ||
413 | 104 | - (NSString *)albumArtistId { | 146 | - (NSString *)albumArtistId { |
414 | 105 | 147 | ||
415 | === modified file 'Music/Models/UOModel.h' | |||
416 | --- Music/Models/UOModel.h 2013-01-02 23:49:22 +0000 | |||
417 | +++ Music/Models/UOModel.h 2013-01-02 23:49:23 +0000 | |||
418 | @@ -8,10 +8,10 @@ | |||
419 | 8 | 8 | ||
420 | 9 | #import <CoreData/CoreData.h> | 9 | #import <CoreData/CoreData.h> |
421 | 10 | 10 | ||
423 | 11 | @class RKManagedObjectMapping; | 11 | @class RKEntityMapping; |
424 | 12 | 12 | ||
425 | 13 | @interface UOModel : NSManagedObject | 13 | @interface UOModel : NSManagedObject |
426 | 14 | + (void)registerMapping; | 14 | + (void)registerMapping; |
428 | 15 | + (RKManagedObjectMapping *)objectMapping; | 15 | + (RKEntityMapping *)objectMapping; |
429 | 16 | + (NSString *)keyPath; | 16 | + (NSString *)keyPath; |
430 | 17 | @end | 17 | @end |
431 | 18 | 18 | ||
432 | === modified file 'Music/Models/UOModel.m' | |||
433 | --- Music/Models/UOModel.m 2013-01-02 23:49:22 +0000 | |||
434 | +++ Music/Models/UOModel.m 2013-01-02 23:49:23 +0000 | |||
435 | @@ -13,13 +13,18 @@ | |||
436 | 13 | 13 | ||
437 | 14 | + (void)registerMapping { | 14 | + (void)registerMapping { |
438 | 15 | RKObjectManager *manager = [RKObjectManager sharedManager]; | 15 | RKObjectManager *manager = [RKObjectManager sharedManager]; |
440 | 16 | [manager.mappingProvider setMapping:[self objectMapping] forKeyPath:[self keyPath]]; | 16 | |
441 | 17 | RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[self objectMapping] | ||
442 | 18 | pathPattern:nil | ||
443 | 19 | keyPath:[self keyPath] | ||
444 | 20 | statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]; | ||
445 | 21 | [manager addResponseDescriptor:responseDescriptor]; | ||
446 | 17 | } | 22 | } |
447 | 18 | 23 | ||
449 | 19 | + (RKManagedObjectMapping *)objectMapping { | 24 | + (RKEntityMapping *)objectMapping { |
450 | 20 | RKObjectManager *manager = [RKObjectManager sharedManager]; | 25 | RKObjectManager *manager = [RKObjectManager sharedManager]; |
451 | 21 | 26 | ||
453 | 22 | RKManagedObjectMapping *mapping = [RKManagedObjectMapping mappingForClass:[self class] inManagedObjectStore:manager.objectStore]; | 27 | RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:@"" inManagedObjectStore:manager.managedObjectStore]; |
454 | 23 | return mapping; | 28 | return mapping; |
455 | 24 | } | 29 | } |
456 | 25 | 30 | ||
457 | 26 | 31 | ||
458 | === added file 'Music/Utilities/UOWebServiceController.h' | |||
459 | --- Music/Utilities/UOWebServiceController.h 1970-01-01 00:00:00 +0000 | |||
460 | +++ Music/Utilities/UOWebServiceController.h 2013-01-02 23:49:23 +0000 | |||
461 | @@ -0,0 +1,39 @@ | |||
462 | 1 | // | ||
463 | 2 | // UOWebServiceController.h | ||
464 | 3 | // U1Music | ||
465 | 4 | // | ||
466 | 5 | // Created by Paul Hummer on 12/12/12. | ||
467 | 6 | // Copyright (c) 2012 Canonical. All rights reserved. | ||
468 | 7 | // | ||
469 | 8 | |||
470 | 9 | #import <Foundation/Foundation.h> | ||
471 | 10 | #import <RestKit/RestKit.h> | ||
472 | 11 | |||
473 | 12 | #define ALBUMS_LAST_UPDATED @"albumsLastUpdated" | ||
474 | 13 | #define ARTISTS_LAST_UPDATED @"artistsLastUpdated" | ||
475 | 14 | #define PLAYLISTS_LAST_UPDATED @"playlistsLastUpdated" | ||
476 | 15 | #define SONGS_LAST_UPDATED @"songsLastUpdated" | ||
477 | 16 | |||
478 | 17 | @protocol UOWebServiceDelegate <NSObject> | ||
479 | 18 | |||
480 | 19 | - (void)webserviceUpdateComplete; | ||
481 | 20 | - (void)webserviceUpdateError:(NSError *)error; | ||
482 | 21 | |||
483 | 22 | @end | ||
484 | 23 | |||
485 | 24 | @interface UOWebServiceController : NSObject | ||
486 | 25 | + (UOWebServiceController *)controller; | ||
487 | 26 | |||
488 | 27 | - (void)updateAlbums:(id<UOWebServiceDelegate>)delegate; | ||
489 | 28 | - (void)updateAlbums:(id<UOWebServiceDelegate>)delegate clearCache:(BOOL)clearCache; | ||
490 | 29 | |||
491 | 30 | - (void)updateArtists:(id<UOWebServiceDelegate>)delegate; | ||
492 | 31 | - (void)updateArtists:(id<UOWebServiceDelegate>)delegate clearCache:(BOOL)clearCache; | ||
493 | 32 | |||
494 | 33 | - (void)updatePlaylists:(id<UOWebServiceDelegate>)delegate; | ||
495 | 34 | - (void)updatePlaylists:(id<UOWebServiceDelegate>)delegate clearCache:(BOOL)clearCache; | ||
496 | 35 | |||
497 | 36 | - (void)updateSongs:(id<UOWebServiceDelegate>)delegate; | ||
498 | 37 | - (void)updateSongs:(id<UOWebServiceDelegate>)delegate clearCache:(BOOL)clearCache; | ||
499 | 38 | |||
500 | 39 | @end | ||
501 | 0 | 40 | ||
502 | === added file 'Music/Utilities/UOWebServiceController.m' | |||
503 | --- Music/Utilities/UOWebServiceController.m 1970-01-01 00:00:00 +0000 | |||
504 | +++ Music/Utilities/UOWebServiceController.m 2013-01-02 23:49:23 +0000 | |||
505 | @@ -0,0 +1,204 @@ | |||
506 | 1 | // | ||
507 | 2 | // UOWebServiceController.m | ||
508 | 3 | // U1Music | ||
509 | 4 | // | ||
510 | 5 | // Created by Paul Hummer on 12/12/12. | ||
511 | 6 | // Copyright (c) 2012 Canonical. All rights reserved. | ||
512 | 7 | // | ||
513 | 8 | |||
514 | 9 | #import "UOWebServiceController.h" | ||
515 | 10 | #import <RestKit/RestKit.h> | ||
516 | 11 | #import <RestKit/CoreData.h> | ||
517 | 12 | #import "UONetworkStatusCoordinator.h" | ||
518 | 13 | #import "UOAuthManager.h" | ||
519 | 14 | #import "AppDelegate.h" | ||
520 | 15 | |||
521 | 16 | #import "Album.h" | ||
522 | 17 | #import "Artist.h" | ||
523 | 18 | #import "Playlist.h" | ||
524 | 19 | #import "Song.h" | ||
525 | 20 | |||
526 | 21 | @interface UOWebServiceController () | ||
527 | 22 | - (void)updateAlbumsWithBlock:(void(^)(void))completionBlock; | ||
528 | 23 | - (void)updateArtistsWithBlock:(void(^)(void))completionBlock; | ||
529 | 24 | - (void)updateSongsWithBlock:(void(^)(void))completionBlock; | ||
530 | 25 | @end | ||
531 | 26 | |||
532 | 27 | @implementation UOWebServiceController | ||
533 | 28 | |||
534 | 29 | - (id)init { | ||
535 | 30 | self = [super init]; | ||
536 | 31 | [self initRestKit]; | ||
537 | 32 | return self; | ||
538 | 33 | } | ||
539 | 34 | |||
540 | 35 | #pragma mark - Static methods | ||
541 | 36 | |||
542 | 37 | + (UOWebServiceController *)controller { | ||
543 | 38 | static UOWebServiceController *instance = nil; | ||
544 | 39 | static dispatch_once_t once; | ||
545 | 40 | dispatch_once(&once, ^{ | ||
546 | 41 | instance = [[UOWebServiceController alloc] init]; | ||
547 | 42 | }); | ||
548 | 43 | return instance; | ||
549 | 44 | } | ||
550 | 45 | |||
551 | 46 | #pragma mark - Network operations | ||
552 | 47 | |||
553 | 48 | - (void)updateAlbums:(id<UOWebServiceDelegate>)delegate clearCache:(BOOL)clearCache { | ||
554 | 49 | if (clearCache || [self needsUpdating:ALBUMS_LAST_UPDATED]) { | ||
555 | 50 | [self updateArtistsWithBlock:^(void) { | ||
556 | 51 | [[RKObjectManager sharedManager] getObjectsAtPath:@"albums/" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { | ||
557 | 52 | [delegate webserviceUpdateComplete]; | ||
558 | 53 | } failure:^(RKObjectRequestOperation *operation, NSError *error) { | ||
559 | 54 | [[NSUserDefaults standardUserDefaults] setObject:nil forKey:ALBUMS_LAST_UPDATED]; | ||
560 | 55 | [delegate webserviceUpdateError:error]; | ||
561 | 56 | }]; | ||
562 | 57 | }]; | ||
563 | 58 | } | ||
564 | 59 | } | ||
565 | 60 | |||
566 | 61 | - (void)updateAlbums:(id<UOWebServiceDelegate>)delegate { | ||
567 | 62 | [self updateAlbums:delegate clearCache:NO]; | ||
568 | 63 | } | ||
569 | 64 | |||
570 | 65 | - (void)updateAlbumsWithBlock:(void (^)(void))completionBlock { | ||
571 | 66 | if ([self needsUpdating:ALBUMS_LAST_UPDATED]) { | ||
572 | 67 | [self updateArtistsWithBlock:^(void) { | ||
573 | 68 | [[RKObjectManager sharedManager] getObjectsAtPath:@"albums/" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { | ||
574 | 69 | [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:ALBUMS_LAST_UPDATED]; | ||
575 | 70 | completionBlock(); | ||
576 | 71 | } failure:^(RKObjectRequestOperation *operation, NSError *error) { | ||
577 | 72 | [[NSUserDefaults standardUserDefaults] setObject:nil forKey:ALBUMS_LAST_UPDATED]; | ||
578 | 73 | }]; | ||
579 | 74 | }]; | ||
580 | 75 | } else { | ||
581 | 76 | completionBlock(); | ||
582 | 77 | } | ||
583 | 78 | } | ||
584 | 79 | |||
585 | 80 | - (void)updateArtists:(id<UOWebServiceDelegate>)delegate clearCache:(BOOL)clearCache { | ||
586 | 81 | if (clearCache || [self needsUpdating:ARTISTS_LAST_UPDATED]) { | ||
587 | 82 | [[RKObjectManager sharedManager] getObjectsAtPath:@"artists/" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { | ||
588 | 83 | [delegate webserviceUpdateComplete]; | ||
589 | 84 | } failure:^(RKObjectRequestOperation *operation, NSError *error) { | ||
590 | 85 | [[NSUserDefaults standardUserDefaults] setObject:nil forKey:ARTISTS_LAST_UPDATED]; | ||
591 | 86 | [delegate webserviceUpdateError:error]; | ||
592 | 87 | }]; | ||
593 | 88 | } | ||
594 | 89 | } | ||
595 | 90 | |||
596 | 91 | - (void)updateArtists:(id<UOWebServiceDelegate>)delegate { | ||
597 | 92 | [self updateArtists:delegate clearCache:NO]; | ||
598 | 93 | } | ||
599 | 94 | |||
600 | 95 | - (void)updateArtistsWithBlock:(void(^)(void))completionBlock { | ||
601 | 96 | if ([self needsUpdating:ARTISTS_LAST_UPDATED]) { | ||
602 | 97 | [[RKObjectManager sharedManager] getObjectsAtPath:@"artists/" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { | ||
603 | 98 | [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:ARTISTS_LAST_UPDATED]; | ||
604 | 99 | completionBlock(); | ||
605 | 100 | } failure:^(RKObjectRequestOperation *operation, NSError *error) { | ||
606 | 101 | [[NSUserDefaults standardUserDefaults] setObject:nil forKey:ARTISTS_LAST_UPDATED]; | ||
607 | 102 | }]; | ||
608 | 103 | } else { | ||
609 | 104 | completionBlock(); | ||
610 | 105 | } | ||
611 | 106 | } | ||
612 | 107 | |||
613 | 108 | - (void)updatePlaylists:(id<UOWebServiceDelegate>)delegate clearCache:(BOOL)clearCache { | ||
614 | 109 | if (clearCache || [self needsUpdating:PLAYLISTS_LAST_UPDATED]) { | ||
615 | 110 | [self updateSongsWithBlock:^(void) { | ||
616 | 111 | [[RKObjectManager sharedManager] getObjectsAtPath:@"playlists/" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { | ||
617 | 112 | [delegate webserviceUpdateComplete]; | ||
618 | 113 | } failure:^(RKObjectRequestOperation *operation, NSError *error) { | ||
619 | 114 | [[NSUserDefaults standardUserDefaults] setObject:nil forKey:PLAYLISTS_LAST_UPDATED]; | ||
620 | 115 | [delegate webserviceUpdateError:error]; | ||
621 | 116 | }]; | ||
622 | 117 | }]; | ||
623 | 118 | } | ||
624 | 119 | } | ||
625 | 120 | |||
626 | 121 | - (void)updatePlaylists:(id<UOWebServiceDelegate>)delegate { | ||
627 | 122 | [self updatePlaylists:delegate clearCache:NO]; | ||
628 | 123 | } | ||
629 | 124 | |||
630 | 125 | - (void)updateSongs:(id<UOWebServiceDelegate>)delegate clearCache:(BOOL)clearCache { | ||
631 | 126 | if (clearCache || [self needsUpdating:SONGS_LAST_UPDATED]) { | ||
632 | 127 | [self updateAlbumsWithBlock:^(void) { | ||
633 | 128 | [[RKObjectManager sharedManager] getObjectsAtPath:@"songs/" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { | ||
634 | 129 | [delegate webserviceUpdateComplete]; | ||
635 | 130 | } failure:^(RKObjectRequestOperation *operation, NSError *error) { | ||
636 | 131 | [[NSUserDefaults standardUserDefaults] setObject:nil forKey:SONGS_LAST_UPDATED]; | ||
637 | 132 | [delegate webserviceUpdateError:error]; | ||
638 | 133 | }]; | ||
639 | 134 | }]; | ||
640 | 135 | } | ||
641 | 136 | } | ||
642 | 137 | |||
643 | 138 | - (void)updateSongs:(id<UOWebServiceDelegate>)delegate { | ||
644 | 139 | [self updateSongs:delegate clearCache:NO]; | ||
645 | 140 | } | ||
646 | 141 | |||
647 | 142 | - (void)updateSongsWithBlock:(void (^)(void))completionBlock { | ||
648 | 143 | if ([self needsUpdating:SONGS_LAST_UPDATED]) { | ||
649 | 144 | [self updateAlbumsWithBlock:^(void) { | ||
650 | 145 | [[RKObjectManager sharedManager] getObjectsAtPath:@"songs/" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { | ||
651 | 146 | [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:SONGS_LAST_UPDATED]; | ||
652 | 147 | completionBlock(); | ||
653 | 148 | } failure:^(RKObjectRequestOperation *operation, NSError *error) { | ||
654 | 149 | [[NSUserDefaults standardUserDefaults] setObject:nil forKey:SONGS_LAST_UPDATED]; | ||
655 | 150 | }]; | ||
656 | 151 | }]; | ||
657 | 152 | } else { | ||
658 | 153 | completionBlock(); | ||
659 | 154 | } | ||
660 | 155 | } | ||
661 | 156 | |||
662 | 157 | #pragma mark - Private methods | ||
663 | 158 | |||
664 | 159 | - (BOOL)needsUpdating:(NSString *)key { | ||
665 | 160 | int interval = -(60*60*24*5); // 5 days ago | ||
666 | 161 | NSDate *freshInterval = [NSDate dateWithTimeIntervalSinceNow:interval]; | ||
667 | 162 | NSDate *lastUpdatedAt = [[NSUserDefaults standardUserDefaults] objectForKey:key]; | ||
668 | 163 | |||
669 | 164 | BOOL updateNeeded = (lastUpdatedAt == nil || [freshInterval compare:lastUpdatedAt] == NSOrderedDescending); | ||
670 | 165 | if (updateNeeded) { | ||
671 | 166 | [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:key]; | ||
672 | 167 | } | ||
673 | 168 | return updateNeeded; | ||
674 | 169 | } | ||
675 | 170 | |||
676 | 171 | - (void)initRestKit { | ||
677 | 172 | |||
678 | 173 | NSURL *baseUrl = [NSURL URLWithString:@"https://one.ubuntu.com/api/music/v2/"]; | ||
679 | 174 | RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseUrl]; | ||
680 | 175 | |||
681 | 176 | /* Handle Plaintext auth */ | ||
682 | 177 | NSURLRequest *echo = [UOAuthManager oauthRequestForPath:[baseUrl path]]; | ||
683 | 178 | [objectManager.HTTPClient setDefaultHeader:@"Authorization" value:[echo valueForHTTPHeaderField:@"Authorization"]]; | ||
684 | 179 | [objectManager.HTTPClient setDefaultHeader:@"Accept-Encoding" value:[echo valueForHTTPHeaderField:@"Accept-Encoding"]]; | ||
685 | 180 | [objectManager.HTTPClient setDefaultHeader:@"User-Agent" value:[echo valueForHTTPHeaderField:@"User-Agent"]]; | ||
686 | 181 | |||
687 | 182 | /* Show animated network I/O indicator when doing network I/O */ | ||
688 | 183 | [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES]; | ||
689 | 184 | |||
690 | 185 | /* Set up managed object store */ | ||
691 | 186 | NSManagedObjectModel *managedObjectModel = [[AppDelegate delegate] managedObjectModel]; | ||
692 | 187 | RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel]; | ||
693 | 188 | |||
694 | 189 | /* Why the hell is RestKit not smart enough to do this automatically? Annoy. */ | ||
695 | 190 | NSError *error; | ||
696 | 191 | [managedObjectStore addSQLitePersistentStoreAtPath:[RKApplicationDataDirectory() stringByAppendingPathComponent:@"UOMusic.sqlite"] fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error]; | ||
697 | 192 | if (error) { | ||
698 | 193 | abort(); | ||
699 | 194 | } | ||
700 | 195 | [objectManager setManagedObjectStore:managedObjectStore]; | ||
701 | 196 | [managedObjectStore createManagedObjectContexts]; | ||
702 | 197 | |||
703 | 198 | [Album registerMapping]; | ||
704 | 199 | [Artist registerMapping]; | ||
705 | 200 | [Playlist registerMapping]; | ||
706 | 201 | [Song registerMapping]; | ||
707 | 202 | } | ||
708 | 203 | |||
709 | 204 | @end | ||
710 | 0 | 205 | ||
711 | === modified file 'Music/View Controllers/AlbumViewController.h' | |||
712 | --- Music/View Controllers/AlbumViewController.h 2012-11-18 16:01:56 +0000 | |||
713 | +++ Music/View Controllers/AlbumViewController.h 2013-01-02 23:49:23 +0000 | |||
714 | @@ -11,5 +11,5 @@ | |||
715 | 11 | @class Album; | 11 | @class Album; |
716 | 12 | 12 | ||
717 | 13 | @interface AlbumViewController : UIViewController | 13 | @interface AlbumViewController : UIViewController |
719 | 14 | @property (nonatomic, retain) Album *album; | 14 | @property (nonatomic, retain) NSString *albumId; |
720 | 15 | @end | 15 | @end |
721 | 16 | 16 | ||
722 | === modified file 'Music/View Controllers/AlbumViewController.m' | |||
723 | --- Music/View Controllers/AlbumViewController.m 2013-01-02 23:49:22 +0000 | |||
724 | +++ Music/View Controllers/AlbumViewController.m 2013-01-02 23:49:23 +0000 | |||
725 | @@ -11,10 +11,12 @@ | |||
726 | 11 | #import <RestKit/RestKit.h> | 11 | #import <RestKit/RestKit.h> |
727 | 12 | #import "SongCell.h" | 12 | #import "SongCell.h" |
728 | 13 | #import "Song.h" | 13 | #import "Song.h" |
730 | 14 | #import "UONetworkStatusCoordinator.h" | 14 | #import "UOWebServiceController.h" |
731 | 15 | 15 | ||
733 | 16 | @interface AlbumViewController () <RKObjectLoaderDelegate, UITableViewDataSource> { | 16 | @interface AlbumViewController () <UITableViewDataSource, UOWebServiceDelegate> { |
734 | 17 | NSArray *tableData; | 17 | NSArray *tableData; |
735 | 18 | |||
736 | 19 | Album *album; | ||
737 | 18 | } | 20 | } |
738 | 19 | @property (weak, nonatomic) IBOutlet UIImageView *albumArt; | 21 | @property (weak, nonatomic) IBOutlet UIImageView *albumArt; |
739 | 20 | @property (weak, nonatomic) IBOutlet UILabel *albumTitle; | 22 | @property (weak, nonatomic) IBOutlet UILabel *albumTitle; |
740 | @@ -24,18 +26,26 @@ | |||
741 | 24 | @end | 26 | @end |
742 | 25 | 27 | ||
743 | 26 | @implementation AlbumViewController | 28 | @implementation AlbumViewController |
744 | 29 | @synthesize albumId = _albumId; | ||
745 | 27 | 30 | ||
746 | 28 | - (void)viewDidLoad { | 31 | - (void)viewDidLoad { |
747 | 29 | [self.tableView setDataSource:self]; | 32 | [self.tableView setDataSource:self]; |
748 | 30 | } | 33 | } |
749 | 31 | 34 | ||
750 | 32 | - (void)viewWillAppear:(BOOL)animated { | 35 | - (void)viewWillAppear:(BOOL)animated { |
757 | 33 | [_albumTitle setText:_album.title]; | 36 | [self fetchAlbum]; |
758 | 34 | //[_albumDescription setText:_album.artist]; | 37 | |
759 | 35 | tableData = [NSArray array]; | 38 | |
760 | 36 | [self.tableView reloadData]; | 39 | [_albumTitle setText:album.title]; |
761 | 37 | 40 | [_albumDescription setText:album.artist.name]; | |
762 | 38 | [self update]; | 41 | |
763 | 42 | if ([album.songs count]) { | ||
764 | 43 | NSArray *sortDescriptors = [NSArray arrayWithObjects:[[NSSortDescriptor alloc] initWithKey:@"track" ascending:NO], nil]; | ||
765 | 44 | tableData = [album.songs sortedArrayUsingDescriptors:sortDescriptors]; | ||
766 | 45 | [self.tableView reloadData]; | ||
767 | 46 | } else { | ||
768 | 47 | [[UOWebServiceController controller] updateSongs:self]; | ||
769 | 48 | } | ||
770 | 39 | } | 49 | } |
771 | 40 | 50 | ||
772 | 41 | - (void)viewDidUnload { | 51 | - (void)viewDidUnload { |
773 | @@ -62,24 +72,41 @@ | |||
774 | 62 | 72 | ||
775 | 63 | #pragma mark - Private methods | 73 | #pragma mark - Private methods |
776 | 64 | 74 | ||
788 | 65 | - (void)update { | 75 | - (void)fetchAlbum { |
789 | 66 | [UONetworkStatusCoordinator addNetworkActivity]; | 76 | NSManagedObjectContext *managedObjectContext = [[[RKObjectManager sharedManager] managedObjectStore] persistentStoreManagedObjectContext]; |
790 | 67 | 77 | ||
791 | 68 | NSString *endpoint = [NSString stringWithFormat:@"/albums/%@/", _album.albumId]; | 78 | NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; |
792 | 69 | [[RKObjectManager sharedManager] loadObjectsAtResourcePath:endpoint delegate:self]; | 79 | NSEntityDescription *entity = [NSEntityDescription entityForName:@"Album" inManagedObjectContext:managedObjectContext]; |
793 | 70 | } | 80 | [fetchRequest setEntity:entity]; |
794 | 71 | 81 | ||
795 | 72 | #pragma mark - RKObjectLoaderDelegate methods | 82 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(albumId = %@)", _albumId]; |
796 | 73 | 83 | [fetchRequest setPredicate:predicate]; | |
797 | 74 | - (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error { | 84 | |
798 | 75 | [UONetworkStatusCoordinator removeNetworkActivity]; | 85 | NSError *error; |
799 | 86 | NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error]; | ||
800 | 87 | if (error || [results count] != 1) { | ||
801 | 88 | abort(); | ||
802 | 89 | } | ||
803 | 90 | album = [results objectAtIndex:0]; | ||
804 | 91 | } | ||
805 | 92 | |||
806 | 93 | #pragma mark - UOWebServiceDelegate methods | ||
807 | 94 | |||
808 | 95 | - (void)webserviceUpdateComplete { | ||
809 | 96 | NSManagedObjectContext *managedObjectContext = [[[RKObjectManager sharedManager] managedObjectStore] persistentStoreManagedObjectContext]; | ||
810 | 97 | [managedObjectContext refreshObject:album mergeChanges:NO]; | ||
811 | 98 | |||
812 | 99 | NSArray *sortDescriptors = [NSArray arrayWithObjects:[[NSSortDescriptor alloc] initWithKey:@"dearticlizedTitle" ascending:YES], nil]; | ||
813 | 100 | tableData = [album.songs sortedArrayUsingDescriptors:sortDescriptors]; | ||
814 | 101 | |||
815 | 102 | [self.tableView reloadData]; | ||
816 | 103 | } | ||
817 | 104 | |||
818 | 105 | - (void)webserviceUpdateError:(NSError *)error { | ||
819 | 106 | if ([error code] == 2) { // Network is down. | ||
820 | 107 | return; | ||
821 | 108 | } | ||
822 | 76 | NSLog(@"Error: %@", [error localizedDescription]); | 109 | NSLog(@"Error: %@", [error localizedDescription]); |
823 | 77 | } | 110 | } |
824 | 78 | 111 | ||
825 | 79 | - (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects { | ||
826 | 80 | [UONetworkStatusCoordinator removeNetworkActivity]; | ||
827 | 81 | tableData = [objects copy]; | ||
828 | 82 | [self.tableView reloadData]; | ||
829 | 83 | } | ||
830 | 84 | |||
831 | 85 | @end | 112 | @end |
832 | 86 | 113 | ||
833 | === modified file 'Music/View Controllers/AlbumsViewController.m' | |||
834 | --- Music/View Controllers/AlbumsViewController.m 2013-01-02 23:49:22 +0000 | |||
835 | +++ Music/View Controllers/AlbumsViewController.m 2013-01-02 23:49:23 +0000 | |||
836 | @@ -12,6 +12,7 @@ | |||
837 | 12 | #import "Album.h" | 12 | #import "Album.h" |
838 | 13 | #import "AlbumCell.h" | 13 | #import "AlbumCell.h" |
839 | 14 | #import "AlbumViewController.h" | 14 | #import "AlbumViewController.h" |
840 | 15 | #import "UOWebServiceController.h" | ||
841 | 15 | 16 | ||
842 | 16 | @interface AlbumsViewController () | 17 | @interface AlbumsViewController () |
843 | 17 | 18 | ||
844 | @@ -21,8 +22,10 @@ | |||
845 | 21 | 22 | ||
846 | 22 | #pragma mark - UOIndexedViewControllers methods | 23 | #pragma mark - UOIndexedViewControllers methods |
847 | 23 | 24 | ||
850 | 24 | - (NSString *)endpoint { | 25 | - (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath { |
851 | 25 | return @"/albums/"; | 26 | Album *album = [self.fetchedResultsController objectAtIndexPath:indexPath]; |
852 | 27 | AlbumCell *albumCell = (AlbumCell *)cell; | ||
853 | 28 | [albumCell setAlbum:album]; | ||
854 | 26 | } | 29 | } |
855 | 27 | 30 | ||
856 | 28 | - (NSString *)entityName { | 31 | - (NSString *)entityName { |
857 | @@ -30,7 +33,7 @@ | |||
858 | 30 | } | 33 | } |
859 | 31 | 34 | ||
860 | 32 | - (NSString *)lastUpdatedKey { | 35 | - (NSString *)lastUpdatedKey { |
862 | 33 | return @"albumsLastUpdated"; | 36 | return ALBUMS_LAST_UPDATED; |
863 | 34 | } | 37 | } |
864 | 35 | 38 | ||
865 | 36 | - (NSArray *)sortDescriptors { | 39 | - (NSArray *)sortDescriptors { |
866 | @@ -39,10 +42,8 @@ | |||
867 | 39 | nil]; | 42 | nil]; |
868 | 40 | } | 43 | } |
869 | 41 | 44 | ||
874 | 42 | - (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath { | 45 | - (void)update { |
875 | 43 | Album *album = [self.fetchedResultsController objectAtIndexPath:indexPath]; | 46 | [[UOWebServiceController controller] updateAlbums:self]; |
872 | 44 | AlbumCell *albumCell = (AlbumCell *)cell; | ||
873 | 45 | [albumCell setAlbum:album]; | ||
876 | 46 | } | 47 | } |
877 | 47 | 48 | ||
878 | 48 | #pragma mark - Storyboard methods | 49 | #pragma mark - Storyboard methods |
879 | @@ -53,7 +54,7 @@ | |||
880 | 53 | NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; | 54 | NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; |
881 | 54 | Album *album = [self.fetchedResultsController objectAtIndexPath:indexPath]; | 55 | Album *album = [self.fetchedResultsController objectAtIndexPath:indexPath]; |
882 | 55 | 56 | ||
884 | 56 | albumViewController.album = album; | 57 | albumViewController.albumId = album.albumId; |
885 | 57 | } | 58 | } |
886 | 58 | 59 | ||
887 | 59 | @end | 60 | @end |
888 | 60 | 61 | ||
889 | === modified file 'Music/View Controllers/ArtistViewController.h' | |||
890 | --- Music/View Controllers/ArtistViewController.h 2012-11-18 15:47:37 +0000 | |||
891 | +++ Music/View Controllers/ArtistViewController.h 2013-01-02 23:49:23 +0000 | |||
892 | @@ -11,5 +11,5 @@ | |||
893 | 11 | @class Artist; | 11 | @class Artist; |
894 | 12 | 12 | ||
895 | 13 | @interface ArtistViewController : UIViewController | 13 | @interface ArtistViewController : UIViewController |
897 | 14 | @property (nonatomic, retain) Artist *artist; | 14 | @property (nonatomic, retain) NSString *artistId; |
898 | 15 | @end | 15 | @end |
899 | 16 | 16 | ||
900 | === modified file 'Music/View Controllers/ArtistViewController.m' | |||
901 | --- Music/View Controllers/ArtistViewController.m 2013-01-02 23:49:22 +0000 | |||
902 | +++ Music/View Controllers/ArtistViewController.m 2013-01-02 23:49:23 +0000 | |||
903 | @@ -14,9 +14,13 @@ | |||
904 | 14 | #import "Album.h" | 14 | #import "Album.h" |
905 | 15 | #import "AlbumCell.h" | 15 | #import "AlbumCell.h" |
906 | 16 | #import "AlbumViewController.h" | 16 | #import "AlbumViewController.h" |
907 | 17 | #import "UOWebServiceController.h" | ||
908 | 18 | #import "AppDelegate.h" | ||
909 | 17 | 19 | ||
911 | 18 | @interface ArtistViewController () <RKObjectLoaderDelegate,UITableViewDataSource> { | 20 | @interface ArtistViewController () <UITableViewDataSource, UOWebServiceDelegate> { |
912 | 19 | NSArray *tableData; | 21 | NSArray *tableData; |
913 | 22 | |||
914 | 23 | Artist *artist; | ||
915 | 20 | } | 24 | } |
916 | 21 | @property (weak, nonatomic) IBOutlet UIImageView *albumArt; | 25 | @property (weak, nonatomic) IBOutlet UIImageView *albumArt; |
917 | 22 | @property (weak, nonatomic) IBOutlet UILabel *artistName; | 26 | @property (weak, nonatomic) IBOutlet UILabel *artistName; |
918 | @@ -26,20 +30,26 @@ | |||
919 | 26 | @end | 30 | @end |
920 | 27 | 31 | ||
921 | 28 | @implementation ArtistViewController | 32 | @implementation ArtistViewController |
923 | 29 | @synthesize artist = _artist; | 33 | @synthesize artistId = _artistId; |
924 | 30 | 34 | ||
925 | 31 | - (void)viewDidLoad { | 35 | - (void)viewDidLoad { |
926 | 32 | [self.tableView setDataSource:self]; | 36 | [self.tableView setDataSource:self]; |
927 | 33 | } | 37 | } |
928 | 34 | 38 | ||
929 | 35 | - (void)viewWillAppear:(BOOL)animated { | 39 | - (void)viewWillAppear:(BOOL)animated { |
934 | 36 | [_artistName setText:_artist.name]; | 40 | [[UOWebServiceController controller] updateAlbums:self]; |
935 | 37 | // TODO: rockstar - fix this once we have that data again. | 41 | [self fetchArtist]; |
936 | 38 | [_artistDescription setText:@"5 songs"]; | 42 | |
937 | 39 | tableData = [NSArray array]; | 43 | [_artistName setText:artist.name]; |
938 | 44 | |||
939 | 45 | NSString *pluralizedNoun = @"albums"; | ||
940 | 46 | if ([artist.albums count] == 1) { | ||
941 | 47 | pluralizedNoun = @"album"; | ||
942 | 48 | } | ||
943 | 49 | [_artistDescription setText:[NSString stringWithFormat:@"%d %@", [artist.albums count], pluralizedNoun]]; | ||
944 | 50 | NSArray *sortDescriptors = [NSArray arrayWithObjects:[[NSSortDescriptor alloc] initWithKey:@"dearticlizedTitle" ascending:YES], nil]; | ||
945 | 51 | tableData = [artist.albums sortedArrayUsingDescriptors:sortDescriptors]; | ||
946 | 40 | [self.tableView reloadData]; | 52 | [self.tableView reloadData]; |
947 | 41 | |||
948 | 42 | [self update]; | ||
949 | 43 | } | 53 | } |
950 | 44 | 54 | ||
951 | 45 | - (void)viewDidUnload { | 55 | - (void)viewDidUnload { |
952 | @@ -64,33 +74,50 @@ | |||
953 | 64 | return cell; | 74 | return cell; |
954 | 65 | } | 75 | } |
955 | 66 | 76 | ||
956 | 67 | #pragma mark - Private methods | ||
957 | 68 | |||
958 | 69 | - (void)update { | ||
959 | 70 | [UONetworkStatusCoordinator addNetworkActivity]; | ||
960 | 71 | |||
961 | 72 | NSString *endpoint = [NSString stringWithFormat:@"/artists/%@/", _artist.artistId]; | ||
962 | 73 | [[RKObjectManager sharedManager] loadObjectsAtResourcePath:endpoint delegate:self]; | ||
963 | 74 | } | ||
964 | 75 | |||
965 | 76 | #pragma mark - RKObjectLoaderDelegate methods | ||
966 | 77 | |||
967 | 78 | - (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error { | ||
968 | 79 | [UONetworkStatusCoordinator removeNetworkActivity]; | ||
969 | 80 | NSLog(@"Error: %@", [error localizedDescription]); | ||
970 | 81 | } | ||
971 | 82 | |||
972 | 83 | - (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects { | ||
973 | 84 | [UONetworkStatusCoordinator removeNetworkActivity]; | ||
974 | 85 | tableData = [objects copy]; | ||
975 | 86 | [self.tableView reloadData]; | ||
976 | 87 | } | ||
977 | 88 | |||
978 | 89 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { | 77 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { |
979 | 90 | AlbumViewController *albumViewController = [segue destinationViewController]; | 78 | AlbumViewController *albumViewController = [segue destinationViewController]; |
980 | 91 | NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; | 79 | NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; |
981 | 92 | Album *album = [tableData objectAtIndex:indexPath.row]; | 80 | Album *album = [tableData objectAtIndex:indexPath.row]; |
983 | 93 | albumViewController.album = album; | 81 | albumViewController.albumId = album.albumId; |
984 | 82 | } | ||
985 | 83 | |||
986 | 84 | #pragma mark - UOWebServiceDelegate methods | ||
987 | 85 | |||
988 | 86 | - (void)webserviceUpdateComplete { | ||
989 | 87 | NSManagedObjectContext *managedObjectContext = [[[RKObjectManager sharedManager] managedObjectStore] persistentStoreManagedObjectContext]; | ||
990 | 88 | [managedObjectContext refreshObject:artist mergeChanges:NO]; | ||
991 | 89 | |||
992 | 90 | NSArray *sortDescriptors = [NSArray arrayWithObjects:[[NSSortDescriptor alloc] initWithKey:@"dearticlizedTitle" ascending:YES], nil]; | ||
993 | 91 | tableData = [artist.albums sortedArrayUsingDescriptors:sortDescriptors]; | ||
994 | 92 | |||
995 | 93 | [self.tableView reloadData]; | ||
996 | 94 | } | ||
997 | 95 | |||
998 | 96 | - (void)webserviceUpdateError:(NSError *)error { | ||
999 | 97 | if ([error code] == 2) { // Network is down. | ||
1000 | 98 | return; | ||
1001 | 99 | } | ||
1002 | 100 | NSLog(@"Error: %@", [error localizedDescription]); | ||
1003 | 101 | } | ||
1004 | 102 | |||
1005 | 103 | #pragma mark - Private methods | ||
1006 | 104 | |||
1007 | 105 | - (void)fetchArtist { | ||
1008 | 106 | NSManagedObjectContext *managedObjectContext = [[[RKObjectManager sharedManager] managedObjectStore] persistentStoreManagedObjectContext]; | ||
1009 | 107 | |||
1010 | 108 | NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; | ||
1011 | 109 | NSEntityDescription *entity = [NSEntityDescription entityForName:@"Artist" inManagedObjectContext:managedObjectContext]; | ||
1012 | 110 | [fetchRequest setEntity:entity]; | ||
1013 | 111 | |||
1014 | 112 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(artistId = %@)", _artistId]; | ||
1015 | 113 | [fetchRequest setPredicate:predicate]; | ||
1016 | 114 | |||
1017 | 115 | NSError *error; | ||
1018 | 116 | NSArray *results = [managedObjectContext executeFetchRequest:fetchRequest error:&error]; | ||
1019 | 117 | if (error || [results count] != 1) { | ||
1020 | 118 | abort(); | ||
1021 | 119 | } | ||
1022 | 120 | artist = [results objectAtIndex:0]; | ||
1023 | 94 | } | 121 | } |
1024 | 95 | 122 | ||
1025 | 96 | @end | 123 | @end |
1026 | 97 | 124 | ||
1027 | === modified file 'Music/View Controllers/ArtistsViewController.m' | |||
1028 | --- Music/View Controllers/ArtistsViewController.m 2013-01-02 23:49:22 +0000 | |||
1029 | +++ Music/View Controllers/ArtistsViewController.m 2013-01-02 23:49:23 +0000 | |||
1030 | @@ -15,6 +15,7 @@ | |||
1031 | 15 | 15 | ||
1032 | 16 | #import "UONetworkStatusCoordinator.h" | 16 | #import "UONetworkStatusCoordinator.h" |
1033 | 17 | #import "ArtistViewController.h" | 17 | #import "ArtistViewController.h" |
1034 | 18 | #import "UOWebServiceController.h" | ||
1035 | 18 | 19 | ||
1036 | 19 | @interface ArtistsViewController () | 20 | @interface ArtistsViewController () |
1037 | 20 | @end | 21 | @end |
1038 | @@ -23,8 +24,11 @@ | |||
1039 | 23 | 24 | ||
1040 | 24 | #pragma mark - UOIndexedViewController methods | 25 | #pragma mark - UOIndexedViewController methods |
1041 | 25 | 26 | ||
1044 | 26 | - (NSString *)endpoint { | 27 | - (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath { |
1045 | 27 | return @"/artists/"; | 28 | Artist *artist = [self.fetchedResultsController objectAtIndexPath:indexPath]; |
1046 | 29 | ArtistCell *artistCell = (ArtistCell *)cell; | ||
1047 | 30 | |||
1048 | 31 | [artistCell setArtist:artist]; | ||
1049 | 28 | } | 32 | } |
1050 | 29 | 33 | ||
1051 | 30 | - (NSString *)entityName { | 34 | - (NSString *)entityName { |
1052 | @@ -32,8 +36,7 @@ | |||
1053 | 32 | } | 36 | } |
1054 | 33 | 37 | ||
1055 | 34 | - (NSString *)lastUpdatedKey { | 38 | - (NSString *)lastUpdatedKey { |
1058 | 35 | 39 | return ARTISTS_LAST_UPDATED; | |
1057 | 36 | return @"artistsLastUpdated"; | ||
1059 | 37 | } | 40 | } |
1060 | 38 | 41 | ||
1061 | 39 | - (NSArray *)sortDescriptors { | 42 | - (NSArray *)sortDescriptors { |
1062 | @@ -42,11 +45,8 @@ | |||
1063 | 42 | nil]; | 45 | nil]; |
1064 | 43 | } | 46 | } |
1065 | 44 | 47 | ||
1071 | 45 | - (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath { | 48 | - (void)update { |
1072 | 46 | Artist *artist = [self.fetchedResultsController objectAtIndexPath:indexPath]; | 49 | [[UOWebServiceController controller] updateArtists:self]; |
1068 | 47 | ArtistCell *artistCell = (ArtistCell *)cell; | ||
1069 | 48 | |||
1070 | 49 | [artistCell setArtist:artist]; | ||
1073 | 50 | } | 50 | } |
1074 | 51 | 51 | ||
1075 | 52 | #pragma mark - Storyboard methods | 52 | #pragma mark - Storyboard methods |
1076 | @@ -56,7 +56,7 @@ | |||
1077 | 56 | NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; | 56 | NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; |
1078 | 57 | Artist *artist = [self.fetchedResultsController objectAtIndexPath:indexPath]; | 57 | Artist *artist = [self.fetchedResultsController objectAtIndexPath:indexPath]; |
1079 | 58 | 58 | ||
1081 | 59 | artistViewController.artist = artist; | 59 | artistViewController.artistId = artist.artistId; |
1082 | 60 | } | 60 | } |
1083 | 61 | 61 | ||
1084 | 62 | @end | 62 | @end |
1085 | 63 | 63 | ||
1086 | === modified file 'Music/View Controllers/PlaylistsViewController.m' | |||
1087 | --- Music/View Controllers/PlaylistsViewController.m 2013-01-02 23:49:22 +0000 | |||
1088 | +++ Music/View Controllers/PlaylistsViewController.m 2013-01-02 23:49:23 +0000 | |||
1089 | @@ -11,6 +11,7 @@ | |||
1090 | 11 | #import "Playlist.h" | 11 | #import "Playlist.h" |
1091 | 12 | #import "PlaylistCell.h" | 12 | #import "PlaylistCell.h" |
1092 | 13 | #import "NSString+Extras.h" | 13 | #import "NSString+Extras.h" |
1093 | 14 | #import "UOWebServiceController.h" | ||
1094 | 14 | 15 | ||
1095 | 15 | @interface PlaylistsViewController () | 16 | @interface PlaylistsViewController () |
1096 | 16 | 17 | ||
1097 | @@ -20,8 +21,10 @@ | |||
1098 | 20 | 21 | ||
1099 | 21 | #pragma mark - UOIndexedViewController methods | 22 | #pragma mark - UOIndexedViewController methods |
1100 | 22 | 23 | ||
1103 | 23 | - (NSString *)endpoint { | 24 | - (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath { |
1104 | 24 | return @"/playlists/"; | 25 | PlaylistCell *playlistCell = (PlaylistCell *)cell; |
1105 | 26 | Playlist *playlist = [self.fetchedResultsController objectAtIndexPath:indexPath]; | ||
1106 | 27 | [playlistCell setPlaylist:playlist]; | ||
1107 | 25 | } | 28 | } |
1108 | 26 | 29 | ||
1109 | 27 | - (NSString *)entityName { | 30 | - (NSString *)entityName { |
1110 | @@ -29,7 +32,7 @@ | |||
1111 | 29 | } | 32 | } |
1112 | 30 | 33 | ||
1113 | 31 | - (NSString *)lastUpdatedKey { | 34 | - (NSString *)lastUpdatedKey { |
1115 | 32 | return @"playlistsLastUpdated"; | 35 | return PLAYLISTS_LAST_UPDATED; |
1116 | 33 | } | 36 | } |
1117 | 34 | 37 | ||
1118 | 35 | - (NSArray *)sortDescriptors { | 38 | - (NSArray *)sortDescriptors { |
1119 | @@ -38,10 +41,8 @@ | |||
1120 | 38 | nil]; | 41 | nil]; |
1121 | 39 | } | 42 | } |
1122 | 40 | 43 | ||
1127 | 41 | - (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath { | 44 | - (void)update { |
1128 | 42 | PlaylistCell *playlistCell = (PlaylistCell *)cell; | 45 | [[UOWebServiceController controller] updatePlaylists:self]; |
1125 | 43 | Playlist *playlist = [self.fetchedResultsController objectAtIndexPath:indexPath]; | ||
1126 | 44 | [playlistCell setPlaylist:playlist]; | ||
1129 | 45 | } | 46 | } |
1130 | 46 | 47 | ||
1131 | 47 | @end | 48 | @end |
1132 | 48 | 49 | ||
1133 | === modified file 'Music/View Controllers/SongsViewController.m' | |||
1134 | --- Music/View Controllers/SongsViewController.m 2013-01-02 23:49:22 +0000 | |||
1135 | +++ Music/View Controllers/SongsViewController.m 2013-01-02 23:49:23 +0000 | |||
1136 | @@ -11,6 +11,7 @@ | |||
1137 | 11 | #import "Song.h" | 11 | #import "Song.h" |
1138 | 12 | #import "SongCell.h" | 12 | #import "SongCell.h" |
1139 | 13 | #import "NSString+Extras.h" | 13 | #import "NSString+Extras.h" |
1140 | 14 | #import "UOWebServiceController.h" | ||
1141 | 14 | 15 | ||
1142 | 15 | @interface SongsViewController () | 16 | @interface SongsViewController () |
1143 | 16 | 17 | ||
1144 | @@ -20,16 +21,12 @@ | |||
1145 | 20 | 21 | ||
1146 | 21 | #pragma mark - UOIndexedViewControllers methods | 22 | #pragma mark - UOIndexedViewControllers methods |
1147 | 22 | 23 | ||
1148 | 23 | - (NSString *)endpoint { | ||
1149 | 24 | return @"/songs/"; | ||
1150 | 25 | } | ||
1151 | 26 | |||
1152 | 27 | - (NSString *)entityName { | 24 | - (NSString *)entityName { |
1153 | 28 | return @"Song"; | 25 | return @"Song"; |
1154 | 29 | } | 26 | } |
1155 | 30 | 27 | ||
1156 | 31 | - (NSString *)lastUpdatedKey { | 28 | - (NSString *)lastUpdatedKey { |
1158 | 32 | return @"songsLastUpdated"; | 29 | return SONGS_LAST_UPDATED; |
1159 | 33 | } | 30 | } |
1160 | 34 | 31 | ||
1161 | 35 | - (NSArray *)sortDescriptors { | 32 | - (NSArray *)sortDescriptors { |
1162 | @@ -44,4 +41,8 @@ | |||
1163 | 44 | [songCell setSong:song]; | 41 | [songCell setSong:song]; |
1164 | 45 | } | 42 | } |
1165 | 46 | 43 | ||
1166 | 44 | - (void)viewWillAppear:(BOOL)animated { | ||
1167 | 45 | [[UOWebServiceController controller] updateSongs:self]; | ||
1168 | 46 | } | ||
1169 | 47 | |||
1170 | 47 | @end | 48 | @end |
1171 | 48 | 49 | ||
1172 | === modified file 'Music/View Controllers/UOIndexedViewController.h' | |||
1173 | --- Music/View Controllers/UOIndexedViewController.h 2013-01-02 23:49:22 +0000 | |||
1174 | +++ Music/View Controllers/UOIndexedViewController.h 2013-01-02 23:49:23 +0000 | |||
1175 | @@ -8,8 +8,9 @@ | |||
1176 | 8 | 8 | ||
1177 | 9 | #import <UIKit/UIKit.h> | 9 | #import <UIKit/UIKit.h> |
1178 | 10 | #import <RestKit/RestKit.h> | 10 | #import <RestKit/RestKit.h> |
1179 | 11 | #import "UOWebServiceController.h" | ||
1180 | 11 | 12 | ||
1182 | 12 | @interface UOIndexedViewController : UITableViewController <NSFetchedResultsControllerDelegate, RKObjectLoaderDelegate> { | 13 | @interface UOIndexedViewController : UITableViewController <NSFetchedResultsControllerDelegate,UOWebServiceDelegate> { |
1183 | 13 | NSMutableDictionary *groupedTableData; | 14 | NSMutableDictionary *groupedTableData; |
1184 | 14 | NSArray *indexes; | 15 | NSArray *indexes; |
1185 | 15 | BOOL indexed; | 16 | BOOL indexed; |
1186 | @@ -26,5 +27,4 @@ | |||
1187 | 26 | 27 | ||
1188 | 27 | - (NSFetchedResultsController *)fetchedResultsController; | 28 | - (NSFetchedResultsController *)fetchedResultsController; |
1189 | 28 | 29 | ||
1190 | 29 | - (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error; | ||
1191 | 30 | @end | 30 | @end |
1192 | 31 | 31 | ||
1193 | === modified file 'Music/View Controllers/UOIndexedViewController.m' | |||
1194 | --- Music/View Controllers/UOIndexedViewController.m 2013-01-02 23:49:22 +0000 | |||
1195 | +++ Music/View Controllers/UOIndexedViewController.m 2013-01-02 23:49:23 +0000 | |||
1196 | @@ -8,11 +8,8 @@ | |||
1197 | 8 | 8 | ||
1198 | 9 | #import "UOIndexedViewController.h" | 9 | #import "UOIndexedViewController.h" |
1199 | 10 | #import <RestKit/RestKit.h> | 10 | #import <RestKit/RestKit.h> |
1200 | 11 | #import "UONetworkStatusCoordinator.h" | ||
1201 | 12 | #import "AppDelegate.h" | 11 | #import "AppDelegate.h" |
1202 | 13 | 12 | ||
1203 | 14 | #define ARTISTS_LAST_UPDATED @"artistsLastUpdateAt" | ||
1204 | 15 | |||
1205 | 16 | @interface UOIndexedViewController () { | 13 | @interface UOIndexedViewController () { |
1206 | 17 | NSFetchedResultsController *_fetchedResultsController; | 14 | NSFetchedResultsController *_fetchedResultsController; |
1207 | 18 | } | 15 | } |
1208 | @@ -21,15 +18,6 @@ | |||
1209 | 21 | 18 | ||
1210 | 22 | @implementation UOIndexedViewController | 19 | @implementation UOIndexedViewController |
1211 | 23 | 20 | ||
1212 | 24 | - (id)initWithStyle:(UITableViewStyle)style | ||
1213 | 25 | { | ||
1214 | 26 | self = [super initWithStyle:style]; | ||
1215 | 27 | if (self) { | ||
1216 | 28 | // Custom initialization | ||
1217 | 29 | } | ||
1218 | 30 | return self; | ||
1219 | 31 | } | ||
1220 | 32 | |||
1221 | 33 | #pragma mark - Abstract methods | 21 | #pragma mark - Abstract methods |
1222 | 34 | 22 | ||
1223 | 35 | - (NSString *)endpoint { | 23 | - (NSString *)endpoint { |
1224 | @@ -56,11 +44,7 @@ | |||
1225 | 56 | return; | 44 | return; |
1226 | 57 | } | 45 | } |
1227 | 58 | 46 | ||
1228 | 59 | #pragma mark - Data retrieval methods | ||
1229 | 60 | |||
1230 | 61 | - (void)update { | 47 | - (void)update { |
1231 | 62 | [UONetworkStatusCoordinator addNetworkActivity]; | ||
1232 | 63 | [[RKObjectManager sharedManager] loadObjectsAtResourcePath:self.endpoint delegate:self]; | ||
1233 | 64 | } | 48 | } |
1234 | 65 | 49 | ||
1235 | 66 | #pragma mark - UIViewController lifecycle | 50 | #pragma mark - UIViewController lifecycle |
1236 | @@ -71,16 +55,7 @@ | |||
1237 | 71 | } | 55 | } |
1238 | 72 | 56 | ||
1239 | 73 | - (void)viewWillAppear:(BOOL)animated { | 57 | - (void)viewWillAppear:(BOOL)animated { |
1250 | 74 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; | 58 | [self update]; |
1241 | 75 | /* In general, using static time difference intervals is bad. However, a precision of "7 days ago" | ||
1242 | 76 | is probably good enough for our needs. | ||
1243 | 77 | */ | ||
1244 | 78 | NSDate *oneWeekAgo = [NSDate dateWithTimeIntervalSinceNow:-604800]; | ||
1245 | 79 | NSDate *lastUpdatedAt = [userDefaults objectForKey:[self lastUpdatedKey]]; | ||
1246 | 80 | if (lastUpdatedAt == nil || [oneWeekAgo compare:lastUpdatedAt] == NSOrderedDescending ) { | ||
1247 | 81 | NSLog(@"Data is stale. Calling update"); | ||
1248 | 82 | [self update]; | ||
1249 | 83 | } | ||
1251 | 84 | } | 59 | } |
1252 | 85 | 60 | ||
1253 | 86 | - (void)didReceiveMemoryWarning | 61 | - (void)didReceiveMemoryWarning |
1254 | @@ -117,8 +92,22 @@ | |||
1255 | 117 | return [self.fetchedResultsController sectionIndexTitles]; | 92 | return [self.fetchedResultsController sectionIndexTitles]; |
1256 | 118 | } | 93 | } |
1257 | 119 | 94 | ||
1258 | 95 | #pragma mark - UOWebServiceDelegate methods | ||
1259 | 96 | |||
1260 | 97 | - (void)webserviceUpdateComplete { | ||
1261 | 98 | _fetchedResultsController = nil; | ||
1262 | 99 | [self.tableView reloadData]; | ||
1263 | 100 | } | ||
1264 | 101 | |||
1265 | 102 | - (void)webserviceUpdateError:(NSError *)error { | ||
1266 | 103 | if ([error code] == 2) { // Network is down. | ||
1267 | 104 | return; | ||
1268 | 105 | } | ||
1269 | 106 | NSLog(@"Error: %@", [error localizedDescription]); | ||
1270 | 107 | } | ||
1271 | 108 | |||
1272 | 120 | #pragma mark - RKObjectLoaderDelegate methods | 109 | #pragma mark - RKObjectLoaderDelegate methods |
1274 | 121 | 110 | /* | |
1275 | 122 | - (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error { | 111 | - (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error { |
1276 | 123 | [UONetworkStatusCoordinator removeNetworkActivity]; | 112 | [UONetworkStatusCoordinator removeNetworkActivity]; |
1277 | 124 | if ([error code] == 2) { // Network is down. | 113 | if ([error code] == 2) { // Network is down. |
1278 | @@ -134,6 +123,7 @@ | |||
1279 | 134 | [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:[self lastUpdatedKey]]; | 123 | [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:[self lastUpdatedKey]]; |
1280 | 135 | [self.tableView reloadData]; | 124 | [self.tableView reloadData]; |
1281 | 136 | } | 125 | } |
1282 | 126 | */ | ||
1283 | 137 | 127 | ||
1284 | 138 | #pragma mark - Fetched results controller | 128 | #pragma mark - Fetched results controller |
1285 | 139 | 129 | ||
1286 | @@ -142,18 +132,12 @@ | |||
1287 | 142 | return _fetchedResultsController; | 132 | return _fetchedResultsController; |
1288 | 143 | } | 133 | } |
1289 | 144 | 134 | ||
1296 | 145 | NSManagedObjectContext *managedObjectContext = [AppDelegate delegate].managedObjectContext; | 135 | NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[self entityName]]; |
1291 | 146 | |||
1292 | 147 | NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; | ||
1293 | 148 | NSEntityDescription *entityDescription = [NSEntityDescription entityForName:[self entityName] inManagedObjectContext:managedObjectContext]; | ||
1294 | 149 | [fetchRequest setEntity:entityDescription]; | ||
1295 | 150 | |||
1297 | 151 | [fetchRequest setFetchBatchSize:20]; | 136 | [fetchRequest setFetchBatchSize:20]; |
1298 | 152 | |||
1299 | 153 | [fetchRequest setSortDescriptors:[self sortDescriptors]]; | 137 | [fetchRequest setSortDescriptors:[self sortDescriptors]]; |
1303 | 154 | 138 | ||
1304 | 155 | _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest | 139 | _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest |
1305 | 156 | managedObjectContext:[RKManagedObjectStore defaultObjectStore].managedObjectContextForCurrentThread | 140 | managedObjectContext:[[AppDelegate delegate] managedObjectContext] |
1306 | 157 | sectionNameKeyPath:[self sectionNameKeyPath] | 141 | sectionNameKeyPath:[self sectionNameKeyPath] |
1307 | 158 | cacheName:nil]; | 142 | cacheName:nil]; |
1308 | 159 | _fetchedResultsController.delegate = self; | 143 | _fetchedResultsController.delegate = self; |
1309 | 160 | 144 | ||
1310 | === modified file 'U1Music.xcodeproj/project.pbxproj' | |||
1311 | --- U1Music.xcodeproj/project.pbxproj 2013-01-02 23:49:22 +0000 | |||
1312 | +++ U1Music.xcodeproj/project.pbxproj 2013-01-02 23:49:23 +0000 | |||
1313 | @@ -32,7 +32,6 @@ | |||
1314 | 32 | 52206BD01655355000A3A0A8 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52206BCF1655354F00A3A0A8 /* SettingsViewController.m */; }; | 32 | 52206BD01655355000A3A0A8 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52206BCF1655354F00A3A0A8 /* SettingsViewController.m */; }; |
1315 | 33 | 52206BE61655BE8700A3A0A8 /* SettingsAuthenticationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52206BE51655BE8700A3A0A8 /* SettingsAuthenticationViewController.m */; }; | 33 | 52206BE61655BE8700A3A0A8 /* SettingsAuthenticationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52206BE51655BE8700A3A0A8 /* SettingsAuthenticationViewController.m */; }; |
1316 | 34 | 52206BE91655BF4900A3A0A8 /* SettingsAboutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52206BE81655BF4900A3A0A8 /* SettingsAboutViewController.m */; }; | 34 | 52206BE91655BF4900A3A0A8 /* SettingsAboutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52206BE81655BF4900A3A0A8 /* SettingsAboutViewController.m */; }; |
1317 | 35 | 52220B9E1672A75F0078D5DC /* RKRequest+Plaintext.m in Sources */ = {isa = PBXBuildFile; fileRef = 52220B9D1672A75F0078D5DC /* RKRequest+Plaintext.m */; }; | ||
1318 | 36 | 523B3CE215B5D64F004394F4 /* grabber.png in Resources */ = {isa = PBXBuildFile; fileRef = 523B3CE015B5D64F004394F4 /* grabber.png */; }; | 35 | 523B3CE215B5D64F004394F4 /* grabber.png in Resources */ = {isa = PBXBuildFile; fileRef = 523B3CE015B5D64F004394F4 /* grabber.png */; }; |
1319 | 37 | 523B3CE315B5D64F004394F4 /* grabber@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 523B3CE115B5D64F004394F4 /* grabber@2x.png */; }; | 36 | 523B3CE315B5D64F004394F4 /* grabber@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 523B3CE115B5D64F004394F4 /* grabber@2x.png */; }; |
1320 | 38 | 523B3CF915B73BA0004394F4 /* download-grey.png in Resources */ = {isa = PBXBuildFile; fileRef = 523B3CF515B73BA0004394F4 /* download-grey.png */; }; | 37 | 523B3CF915B73BA0004394F4 /* download-grey.png in Resources */ = {isa = PBXBuildFile; fileRef = 523B3CF515B73BA0004394F4 /* download-grey.png */; }; |
1321 | @@ -83,6 +82,7 @@ | |||
1322 | 83 | 52AC3D811604513E00B4785D /* uncached.png in Resources */ = {isa = PBXBuildFile; fileRef = 52AC3D651604513E00B4785D /* uncached.png */; }; | 82 | 52AC3D811604513E00B4785D /* uncached.png in Resources */ = {isa = PBXBuildFile; fileRef = 52AC3D651604513E00B4785D /* uncached.png */; }; |
1323 | 84 | 52AC3D821604513E00B4785D /* uncached@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52AC3D661604513E00B4785D /* uncached@2x.png */; }; | 83 | 52AC3D821604513E00B4785D /* uncached@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52AC3D661604513E00B4785D /* uncached@2x.png */; }; |
1324 | 85 | 52AC3D841604539000B4785D /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52AC3D831604539000B4785D /* Default-568h@2x.png */; }; | 84 | 52AC3D841604539000B4785D /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 52AC3D831604539000B4785D /* Default-568h@2x.png */; }; |
1325 | 85 | 52B7A030167986BC00243D7D /* UOWebServiceController.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B7A02F167986BC00243D7D /* UOWebServiceController.m */; }; | ||
1326 | 86 | 536D620B1144495400DFCE56 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 536D620A1144495400DFCE56 /* SystemConfiguration.framework */; }; | 86 | 536D620B1144495400DFCE56 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 536D620A1144495400DFCE56 /* SystemConfiguration.framework */; }; |
1327 | 87 | 537DE2D9113F008C00875852 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 537DE2D8113F008C00875852 /* CoreFoundation.framework */; }; | 87 | 537DE2D9113F008C00875852 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 537DE2D8113F008C00875852 /* CoreFoundation.framework */; }; |
1328 | 88 | 53F675D8113B092C00822059 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53F675D7113B092C00822059 /* MediaPlayer.framework */; }; | 88 | 53F675D8113B092C00822059 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53F675D7113B092C00822059 /* MediaPlayer.framework */; }; |
1329 | @@ -152,13 +152,6 @@ | |||
1330 | 152 | remoteGlobalIDString = 25160E78145651060060A5C5; | 152 | remoteGlobalIDString = 25160E78145651060060A5C5; |
1331 | 153 | remoteInfo = RestKitFrameworkTests; | 153 | remoteInfo = RestKitFrameworkTests; |
1332 | 154 | }; | 154 | }; |
1333 | 155 | 52206B9D16550AEE00A3A0A8 /* PBXContainerItemProxy */ = { | ||
1334 | 156 | isa = PBXContainerItemProxy; | ||
1335 | 157 | containerPortal = 52206B8A16550AED00A3A0A8 /* RestKit.xcodeproj */; | ||
1336 | 158 | proxyType = 2; | ||
1337 | 159 | remoteGlobalIDString = 259C301615128079003066A2; | ||
1338 | 160 | remoteInfo = RestKitResources; | ||
1339 | 161 | }; | ||
1340 | 162 | 528515931604F16D004A1F7C /* PBXContainerItemProxy */ = { | 155 | 528515931604F16D004A1F7C /* PBXContainerItemProxy */ = { |
1341 | 163 | isa = PBXContainerItemProxy; | 156 | isa = PBXContainerItemProxy; |
1342 | 164 | containerPortal = 5285158E1604F16B004A1F7C /* UbuntuOneAuthKit.xcodeproj */; | 157 | containerPortal = 5285158E1604F16B004A1F7C /* UbuntuOneAuthKit.xcodeproj */; |
1343 | @@ -219,8 +212,6 @@ | |||
1344 | 219 | 52206BE51655BE8700A3A0A8 /* SettingsAuthenticationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SettingsAuthenticationViewController.m; path = "Music/View Controllers/SettingsAuthenticationViewController.m"; sourceTree = SOURCE_ROOT; }; | 212 | 52206BE51655BE8700A3A0A8 /* SettingsAuthenticationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SettingsAuthenticationViewController.m; path = "Music/View Controllers/SettingsAuthenticationViewController.m"; sourceTree = SOURCE_ROOT; }; |
1345 | 220 | 52206BE71655BF4900A3A0A8 /* SettingsAboutViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SettingsAboutViewController.h; path = "Music/View Controllers/SettingsAboutViewController.h"; sourceTree = SOURCE_ROOT; }; | 213 | 52206BE71655BF4900A3A0A8 /* SettingsAboutViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SettingsAboutViewController.h; path = "Music/View Controllers/SettingsAboutViewController.h"; sourceTree = SOURCE_ROOT; }; |
1346 | 221 | 52206BE81655BF4900A3A0A8 /* SettingsAboutViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SettingsAboutViewController.m; path = "Music/View Controllers/SettingsAboutViewController.m"; sourceTree = SOURCE_ROOT; }; | 214 | 52206BE81655BF4900A3A0A8 /* SettingsAboutViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SettingsAboutViewController.m; path = "Music/View Controllers/SettingsAboutViewController.m"; sourceTree = SOURCE_ROOT; }; |
1347 | 222 | 52220B9C1672A75F0078D5DC /* RKRequest+Plaintext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "RKRequest+Plaintext.h"; path = "Music/Categories/RKRequest+Plaintext.h"; sourceTree = SOURCE_ROOT; }; | ||
1348 | 223 | 52220B9D1672A75F0078D5DC /* RKRequest+Plaintext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "RKRequest+Plaintext.m"; path = "Music/Categories/RKRequest+Plaintext.m"; sourceTree = SOURCE_ROOT; }; | ||
1349 | 224 | 523B3CDC15B4C42F004394F4 /* SongUITableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SongUITableView.h; sourceTree = "<group>"; }; | 215 | 523B3CDC15B4C42F004394F4 /* SongUITableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SongUITableView.h; sourceTree = "<group>"; }; |
1350 | 225 | 523B3CDD15B4C42F004394F4 /* SongUITableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SongUITableView.m; sourceTree = "<group>"; }; | 216 | 523B3CDD15B4C42F004394F4 /* SongUITableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SongUITableView.m; sourceTree = "<group>"; }; |
1351 | 226 | 523B3CE015B5D64F004394F4 /* grabber.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = grabber.png; sourceTree = "<group>"; }; | 217 | 523B3CE015B5D64F004394F4 /* grabber.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = grabber.png; sourceTree = "<group>"; }; |
1352 | @@ -327,6 +318,8 @@ | |||
1353 | 327 | 52AC3D651604513E00B4785D /* uncached.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = uncached.png; sourceTree = "<group>"; }; | 318 | 52AC3D651604513E00B4785D /* uncached.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = uncached.png; sourceTree = "<group>"; }; |
1354 | 328 | 52AC3D661604513E00B4785D /* uncached@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "uncached@2x.png"; sourceTree = "<group>"; }; | 319 | 52AC3D661604513E00B4785D /* uncached@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "uncached@2x.png"; sourceTree = "<group>"; }; |
1355 | 329 | 52AC3D831604539000B4785D /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; }; | 320 | 52AC3D831604539000B4785D /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; }; |
1356 | 321 | 52B7A02E167986BC00243D7D /* UOWebServiceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UOWebServiceController.h; path = Music/Utilities/UOWebServiceController.h; sourceTree = SOURCE_ROOT; }; | ||
1357 | 322 | 52B7A02F167986BC00243D7D /* UOWebServiceController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UOWebServiceController.m; path = Music/Utilities/UOWebServiceController.m; sourceTree = SOURCE_ROOT; }; | ||
1358 | 330 | 536D620A1144495400DFCE56 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; | 323 | 536D620A1144495400DFCE56 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; |
1359 | 331 | 537DE2D8113F008C00875852 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; | 324 | 537DE2D8113F008C00875852 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; |
1360 | 332 | 53F675D7113B092C00822059 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; | 325 | 53F675D7113B092C00822059 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; |
1361 | @@ -666,7 +659,6 @@ | |||
1362 | 666 | 52206B9816550AEE00A3A0A8 /* RestKitTests.octest */, | 659 | 52206B9816550AEE00A3A0A8 /* RestKitTests.octest */, |
1363 | 667 | 52206B9A16550AEE00A3A0A8 /* RestKit.framework */, | 660 | 52206B9A16550AEE00A3A0A8 /* RestKit.framework */, |
1364 | 668 | 52206B9C16550AEE00A3A0A8 /* RestKitFrameworkTests.octest */, | 661 | 52206B9C16550AEE00A3A0A8 /* RestKitFrameworkTests.octest */, |
1365 | 669 | 52206B9E16550AEE00A3A0A8 /* RestKitResources.bundle */, | ||
1366 | 670 | ); | 662 | ); |
1367 | 671 | name = Products; | 663 | name = Products; |
1368 | 672 | sourceTree = "<group>"; | 664 | sourceTree = "<group>"; |
1369 | @@ -736,6 +728,8 @@ | |||
1370 | 736 | children = ( | 728 | children = ( |
1371 | 737 | 5244A7FE1656A10200882601 /* UONetworkStatusCoordinator.h */, | 729 | 5244A7FE1656A10200882601 /* UONetworkStatusCoordinator.h */, |
1372 | 738 | 5244A7FF1656A10200882601 /* UONetworkStatusCoordinator.m */, | 730 | 5244A7FF1656A10200882601 /* UONetworkStatusCoordinator.m */, |
1373 | 731 | 52B7A02E167986BC00243D7D /* UOWebServiceController.h */, | ||
1374 | 732 | 52B7A02F167986BC00243D7D /* UOWebServiceController.m */, | ||
1375 | 739 | ); | 733 | ); |
1376 | 740 | name = Utilities; | 734 | name = Utilities; |
1377 | 741 | sourceTree = "<group>"; | 735 | sourceTree = "<group>"; |
1378 | @@ -745,8 +739,6 @@ | |||
1379 | 745 | children = ( | 739 | children = ( |
1380 | 746 | 5244A8031657245A00882601 /* NSString+Extras.h */, | 740 | 5244A8031657245A00882601 /* NSString+Extras.h */, |
1381 | 747 | 5244A8041657245A00882601 /* NSString+Extras.m */, | 741 | 5244A8041657245A00882601 /* NSString+Extras.m */, |
1382 | 748 | 52220B9C1672A75F0078D5DC /* RKRequest+Plaintext.h */, | ||
1383 | 749 | 52220B9D1672A75F0078D5DC /* RKRequest+Plaintext.m */, | ||
1384 | 750 | ); | 742 | ); |
1385 | 751 | name = Categories; | 743 | name = Categories; |
1386 | 752 | sourceTree = "<group>"; | 744 | sourceTree = "<group>"; |
1387 | @@ -1378,13 +1370,6 @@ | |||
1388 | 1378 | remoteRef = 52206B9B16550AEE00A3A0A8 /* PBXContainerItemProxy */; | 1370 | remoteRef = 52206B9B16550AEE00A3A0A8 /* PBXContainerItemProxy */; |
1389 | 1379 | sourceTree = BUILT_PRODUCTS_DIR; | 1371 | sourceTree = BUILT_PRODUCTS_DIR; |
1390 | 1380 | }; | 1372 | }; |
1391 | 1381 | 52206B9E16550AEE00A3A0A8 /* RestKitResources.bundle */ = { | ||
1392 | 1382 | isa = PBXReferenceProxy; | ||
1393 | 1383 | fileType = wrapper.cfbundle; | ||
1394 | 1384 | path = RestKitResources.bundle; | ||
1395 | 1385 | remoteRef = 52206B9D16550AEE00A3A0A8 /* PBXContainerItemProxy */; | ||
1396 | 1386 | sourceTree = BUILT_PRODUCTS_DIR; | ||
1397 | 1387 | }; | ||
1398 | 1388 | 528515941604F16D004A1F7C /* UbuntuOneAuthKit.a */ = { | 1373 | 528515941604F16D004A1F7C /* UbuntuOneAuthKit.a */ = { |
1399 | 1389 | isa = PBXReferenceProxy; | 1374 | isa = PBXReferenceProxy; |
1400 | 1390 | fileType = archive.ar; | 1375 | fileType = archive.ar; |
1401 | @@ -1531,7 +1516,7 @@ | |||
1402 | 1531 | 5244A81A1657C63700882601 /* PlaylistCell.m in Sources */, | 1516 | 5244A81A1657C63700882601 /* PlaylistCell.m in Sources */, |
1403 | 1532 | 5244A83A165B528800882601 /* UOMusic.xcdatamodeld in Sources */, | 1517 | 5244A83A165B528800882601 /* UOMusic.xcdatamodeld in Sources */, |
1404 | 1533 | 5244A83D165C627900882601 /* UOModel.m in Sources */, | 1518 | 5244A83D165C627900882601 /* UOModel.m in Sources */, |
1406 | 1534 | 52220B9E1672A75F0078D5DC /* RKRequest+Plaintext.m in Sources */, | 1519 | 52B7A030167986BC00243D7D /* UOWebServiceController.m in Sources */, |
1407 | 1535 | ); | 1520 | ); |
1408 | 1536 | runOnlyForDeploymentPostprocessing = 0; | 1521 | runOnlyForDeploymentPostprocessing = 0; |
1409 | 1537 | }; | 1522 | }; |
1410 | 1538 | 1523 | ||
1411 | === modified file 'U1Music_Prefix.pch' | |||
1412 | --- U1Music_Prefix.pch 2012-09-25 21:28:26 +0000 | |||
1413 | +++ U1Music_Prefix.pch 2013-01-02 23:49:23 +0000 | |||
1414 | @@ -10,15 +10,9 @@ | |||
1415 | 10 | 10 | ||
1416 | 11 | #ifdef __OBJC__ | 11 | #ifdef __OBJC__ |
1417 | 12 | #import <Foundation/Foundation.h> | 12 | #import <Foundation/Foundation.h> |
1418 | 13 | #import <MobileCoreServices/MobileCoreServices.h> | ||
1419 | 14 | #import <SystemConfiguration/SystemConfiguration.h> | ||
1420 | 13 | #import <UIKit/UIKit.h> | 15 | #import <UIKit/UIKit.h> |
1426 | 14 | #import <CoreData/CoreData.h> | 16 | |
1422 | 15 | #import "Globals.h" | ||
1423 | 16 | #import "MOC.h" | ||
1424 | 17 | #import "NSManagedObjectContext+Additions.h" | ||
1425 | 18 | #import "NSString+Extras.h" | ||
1427 | 19 | #import "TestFlight.h" | 17 | #import "TestFlight.h" |
1428 | 20 | #define RELEASE_SAFELY(__obj) [__obj release], __obj = nil; | ||
1429 | 21 | |||
1430 | 22 | #define UBUNTU_ONE_SERVICE_NAME @"com.ubuntu.one" | ||
1431 | 23 | #define UBUNTU_ONE_DUMMY_USER_NAME @"_UBUNTU_ONE_USER_NAME" | ||
1432 | 24 | #endif | 18 | #endif |
if ([error code] == 2) { // Network is down.
-- just nitpicking: a constant instead of comment would be better
int interval = -(60*60*24*5); // 5 days ago
-- this update interval feels arbitrary to me. How do we know that I haven't purchased a music album today?
Couple of lines moved in PlaylistsViewCo ntroller. m
-- there was no change intentionally, right? I understand you just found a better place for that snippet.
Would it be difficult to add at least some basic tests exercising the updated Core Data model?
I noticed you've set 'Ubuntu One iOS Client Team' as the reviewer. I think you could go with Ubuntu One Client Engineering, I've already dumped the Android equivalent, as we basically became two one-manned sub-teams of Client Engineering after the re-org :)