Example project: http://cl.ly/360k3M3a2y05
I'm playing with the Reddit API for a school project, and came across this library for using it in Objective-C/Swift.
The professor wants us to get our toes wet with Swift, which I'm happy to do, and the goal of the project is to add an extra function onto an existing website's API. (I chose Reddit obviously.)
The mentioned library doesn't have a way to get all the subscriptions for a particular user (only to get one page at a time with the option to paginate), so I want to add the option to get them all in one clean call.
I'm leveraging the method in the aforementioned library that allows you to paginate, the method looks like this:
- (NSURLSessionDataTask *)subscribedSubredditsInCategory:(RKSubscribedSubredditCategory)category pagination:(RKPagination *)pagination completion:(RKListingCompletionBlock)completion {
NSMutableDictionary *taskParameters = [NSMutableDictionary dictionary];
[taskParameters addEntriesFromDictionary:[pagination dictionaryValue]];
NSString *path = [NSString stringWithFormat:@"subreddits/mine/%@.json", RKStringFromSubscribedSubredditCategory(category)];
return [self getPath:path parameters:taskParameters completion:^(NSHTTPURLResponse *response, id responseObject, NSError *error) {
if (!completion) return;
if (responseObject)
{
// A crude check to see if we have been redirected to the login page:
NSString *path = [[response URL] path];
NSRange range = [path rangeOfString:@"login"];
if (range.location != NSNotFound)
{
completion(nil, nil, [RKClient authenticationRequiredError]);
return;
}
// Parse the response:
NSArray *subredditsJSON = responseObject[@"data"][@"children"];
NSMutableArray *subredditObjects = [[NSMutableArray alloc] initWithCapacity:[subredditsJSON count]];
for (NSDictionary *subredditJSON in subredditsJSON)
{
NSError *mantleError = nil;
RKSubreddit *subreddit = [MTLJSONAdapter modelOfClass:[RKSubreddit class] fromJSONDictionary:subredditJSON error:&mantleError];
if (!mantleError)
{
[subredditObjects addObject:subreddit];
}
}
RKPagination *pagination = [RKPagination paginationFromListingResponse:responseObject];
completion([subredditObjects copy], pagination, nil);
}
else
{
completion(nil, nil, error);
}
}];
}
My addition is rather simple, I just call this above method recursively and save the pagination after each successful request, until there's no pages left, and then return the result:
- (void)allSubscribedSubredditsInCategory:(RKSubscribedSubredditCategory)category completion:(void (^)(NSArray *subreddits, NSError *error))completion {
RKPagination *pagination = [RKPagination paginationWithLimit:100];
[self recursiveSubscribedSubredditsWithPagination:pagination subredditsSoFar:[NSArray array] completion:completion];
}
- (void)recursiveSubscribedSubredditsWithPagination:(RKPagination *)pagination subredditsSoFar:(NSArray *)subredditsSoFar completion:(void (^)(NSArray *subreddits, NSError *error))completion {
[self subscribedSubredditsInCategory:RKSubscribedSubredditCategorySubscriber pagination:pagination completion:^(NSArray *newSubreddits, RKPagination *newPagination, NSError *newError) {
// If pagination is nil, we cannot go any further and have reached the end
if (newPagination == nil) {
NSArray *newSubredditsSoFar = [subredditsSoFar arrayByAddingObjectsFromArray:newSubreddits];
NSArray *subredditsWithoutDuplicates = [[NSSet setWithArray:newSubredditsSoFar] allObjects];
completion(subredditsWithoutDuplicates, newError);
} else {
NSArray *newSubredditsSoFar = [subredditsSoFar arrayByAddingObjectsFromArray:newSubreddits];
[self recursiveSubscribedSubredditsWithPagination:newPagination subredditsSoFar:newSubredditsSoFar completion:completion];
}
}];
}
So it looks like this in my viewDidLoad
of my view controller:
RKClient.sharedClient().signInWithUsername("includedinproject", password: "includedinproject") { (error) -> Void in
RKClient.sharedClient().allSubscribedSubredditsInCategory(.Subscriber, completion: { (subreddits, error) -> Void in
print(subreddits)
}) <-- error occurs here?
}
However, whenever I call it, I get an EXC_BAD_ACCESS
runtime error that doesn't really provide anything other than a memory address, and it appears to be caused at the end of the method in viewDidLoad
, as labeled above.
The weird thing that occurs, however, is that this only occurs seemingly on the iPhone 4s simulator. If I build it to run on say, the newest 6s, it works fine. I'm puzzled (it has to work on all simulators for full points).
I went to my professor about it and he has no idea. We emulated the project in Objective-C (rebuilt the project as an Objective-C one) and the call seems to work fine.
My professor even did something with Instruments (not much experience myself) looking at "Zombies" and enabled it in the project as well, and nothing seemed to give him information either, we're both pretty confused.
What is going on here that's causing it to work great in Objective-C, and in Swift if the device isn't a 4s? Example project is at the top.