I'm making an app with a picture timeline, so far, i've done the following:
the problem is in the step #3. it works, but it loads all of it at the same time and currently 48 pics in a timeline is eating 537Mb of memory. idk what to do to make it smooth and take up less resources like instagram and Facebook.
i display the pics in a uitableviewcontroller. does anybody have any ideas on how to make a timeline?
To fetch the pictures:
if(feedArray.count > 0){
for(NSString *person in feedArray){
int count = [[Globals global] getMiscPicsCountForUser:person];
for(int i = 1; i < count; i++){
[[Globals global] getMiscPicForUser:person :i withFetchedPicture:^(WKImage *image) {
if(image){
[self.thisPersonsTimelineObjects addObject:image];
//[self createTimelineViewForImage:image];
NSLog(@"person: %@ -- count:%i -- temp array count:%lu -- i:%i", person, count, self.thisPersonsTimelineObjects.count ,i);
if(self.thisPersonsTimelineObjects.count == count - 1){
[self sortTimelineByDate];
}
}
}];
}
}
}
-(void)createTimelineViewForImage :(WKImage *)image {
dispatch_async(dispatch_queue_create("timeline", NULL), ^{
dispatch_async(dispatch_get_main_queue(), ^{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:[[NSBundle mainBundle].infoDictionary objectForKey:@"UIMainStoryboardFile"] bundle:[NSBundle mainBundle]];
WKTimelineViewsViewController *view = [storyboard instantiateViewControllerWithIdentifier:@"WKTimelineViewViewController"];
[view initWithImage:image andParentController:self];
view.view.frame = CGRectMake(view.view.frame.origin.x,
view.view.frame.origin.y,
view.view.frame.size.width * 0.95,
view.view.frame.size.height * 0.95);
[self.thisPersonsTimelineViews addObject:view];
[self.tableView reloadData];
});
});
}
-(void)sortTimelineByDate {
if(self.thisPersonsTimelineObjects.count > 0){
NSMutableArray *dateArray = [NSMutableArray array];
for(WKImage *view in self.thisPersonsTimelineObjects){
[dateArray addObject:[view timeStamp]];
}
NSMutableArray *tempArray = [NSMutableArray array];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"self" ascending:NO];
NSArray *descriptors = [NSArray arrayWithObject:descriptor];
NSArray *reverseOrder = [dateArray sortedArrayUsingDescriptors:descriptors];
for(int i = 0; i < reverseOrder.count; i++){
NSDate *date = reverseOrder[i];
for(int j = 0; j < self.thisPersonsTimelineObjects.count; j++){
NSDate *timestamp = [self.thisPersonsTimelineObjects[j] timeStamp];
if(date == timestamp){
[tempArray addObject:self.thisPersonsTimelineObjects[j]];
}
}
}
self.thisPersonsTimelineObjects = [NSMutableArray arrayWithArray:tempArray];
[self.thisPersonsTimelineViews removeAllObjects];
for(WKImage *image in self.thisPersonsTimelineObjects){
[self createTimelineViewForImage:image];
}
}
}
You're encountering an issue because all of the images are pre-fetched. Instead, what you want to do is fetch the images as they are needed, as the user scrolls, and then cache them when downloaded (this is what Instagram and Facebook do).
Firstly, I'd recommend integrating SDWebImage into your project as it makes all of this easier.
Next, you can integrate the following logic:
Here's an example:
1 and 2 (inside your data source):
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
}
PhotoObject *object = [self objects][[indexPath row]];
[[cell imageView] sd_setImageWithURL:[object photoURL]];
return cell;
}
3: (inside the table cell)
-(void)prepareForReuse {
[super prepareForReuse];
[[self imageView] sd_cancelCurrentImageLoad];
[[self imageView] setImage:nil];
}
This will allow images to be only downloaded as they have to be, and you will also automatically cache them using SDWebImage so they will be displayed instantly instead of downloaded if the user scrolls back to an image.