Question

I am putting a twitter feed in my app and no matter what I have tried to do to get the tweets to display in their entirety, I have not been entirely successful. Most tweets show up fine but it's the really long ones that have given me a headache. I thought it was because I was somehow not getting enough lines in my textLabel, but I noticed that if a user has elongated their tweet by hitting enter multiple times the tweets would show up fine. Which leads me to believe somehow it is truncating after a certain amount of characters. I don't know if I'm doing something wrong or if this is just an issue with twitter. If anyone can see anything in my code that is wrong, or could be changed to fix this, please let me know. Thank you

#import "TwitterFeedTVC.h"
#import "TweetVC.h"
#import <QuartzCore/QuartzCore.h>
#import "GTMNSString+HTML.h"

#define REFRESH_HEADER_HEIGHT 52.0f
#define FONT_SIZE 14.0f
#define CELL_CONTENT_WIDTH 320.0f
#define CELL_CONTENT_MARGIN 10.0f


@implementation TwitterFeedTVC

@synthesize textPull, textRelease, textLoading, refreshHeaderView, refreshLabel, refreshArrow, refreshSpinner, twitterFeedName, twitterFeedTitle;

- (id)initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self != nil) 
{
    [self setupStrings]; 
}
return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self != nil)
{
    [self setupStrings];
}
return self;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self != nil)
{
    [self setupStrings];
}
return  self;
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
[super viewDidLoad];
self.twitterFeedTitle.text = self.twitterFeedName;
self.navigationItem.title = self.twitterFeedName;

[self fetchTweets];
[self addPullToRefreshHeader];
}

- (void)fetchTweets
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://api.twitter.com/1/statuses/user_timeline.json?include_rts=true&screen_name=johnnelm9r&count=100"]];

    if (data == nil)
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Warning"
                                                        message:@"Twitter Is Not Responding. Please Try Again Later!"
                                                       delegate:self
                                              cancelButtonTitle:@"Kali Baby" 
                                              otherButtonTitles: nil];

        [alert show];
    }

    else

    {
    NSError *error;

    tweets = [NSJSONSerialization JSONObjectWithData:data
                                             options:kNilOptions
                                               error:&error];
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        [self.tableView reloadData];
    });

});


}

- (void)viewDidUnload
{
[super viewDidUnload];

textPull = nil;
textRelease = nil;
textLoading = nil;
refreshHeaderView = nil;
refreshLabel = nil;
refreshArrow = nil;
refreshSpinner = nil;
}

- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotate
{
return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return tweets.count;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
NSDictionary *tweet = [tweets objectAtIndex:indexPath.row];
NSString *text = [tweet objectForKey:@"text"];

CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), CGFLOAT_MAX);

CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];

CGFloat height = MAX(size.height, 44.0f);

return height + ((CELL_CONTENT_MARGIN * 2) + 9);
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"TweetCell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
    {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

NSDictionary *tweet = [tweets objectAtIndex:indexPath.row];

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
[dateFormatter setDateFormat:@"EEE MMM dd HH:mm:ss +0000 yyyy"];

NSDate *currentDate = [dateFormatter dateFromString:[tweet objectForKey:@"created_at"]];
NSDate *todayDate = [NSDate date];
NSString *date = [dateFormatter stringFromDate:currentDate];

double timeInterval = [currentDate timeIntervalSinceDate:todayDate];
timeInterval = timeInterval * -1;
if (timeInterval < 1)
{
    date = @"never";
}
else if (timeInterval <60)
{
    date = @"less than a minute ago";
}
else if (timeInterval <3600)
{
    int diff = round(timeInterval / 60);
    date = [NSString stringWithFormat:@"%d minutes ago", diff];
}
else if (timeInterval < 86400)
{
    int diff = round(timeInterval / 60 / 60);
    date = [NSString stringWithFormat:@"%d hours ago", diff];
}
else if (timeInterval < 2629743)
{
    int diff = round(timeInterval / 60 / 60 / 24);
    date = [NSString stringWithFormat:@"%d days ago", diff];
}
else
{
    date = @"never";
}

cell.textLabel.text = [[tweet objectForKey:@"text"] gtm_stringByUnescapingFromHTML];
cell.detailTextLabel.text = [NSString stringWithFormat:@"%@", date];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSString *imageUrl = [[tweet objectForKey:@"user"] objectForKey:@"profile_image_url"];
    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]];

    dispatch_async(dispatch_get_main_queue(), ^{
        cell.imageView.image = [UIImage imageWithData:data];
        [cell addSubview:cell.imageView];

    });
});

return cell;
}

- (void)setupStrings
{
textPull = @"Pull Down To Be Fresh...";
textRelease = @"Release To Be Fresh...";
textLoading = @"Getting Loaded...";
}

- (void)addPullToRefreshHeader
{
refreshHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0 - REFRESH_HEADER_HEIGHT, 320, REFRESH_HEADER_HEIGHT)];
refreshHeaderView.backgroundColor = [UIColor clearColor];

refreshLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, REFRESH_HEADER_HEIGHT)];
refreshLabel.backgroundColor = [UIColor clearColor];
refreshLabel.font = [UIFont boldSystemFontOfSize:12.0];
refreshLabel.textAlignment = UITextAlignmentCenter;

refreshArrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"KrizzOpener.png"]];
refreshArrow.frame = CGRectMake(floorf((REFRESH_HEADER_HEIGHT - 27) / 2),
                                (floorf(REFRESH_HEADER_HEIGHT - 44) / 2),
                                27, 44);

refreshSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
refreshSpinner.frame = CGRectMake(floorf(floorf(REFRESH_HEADER_HEIGHT - 20) / 2), floorf((REFRESH_HEADER_HEIGHT - 20) / 2), 20, 20);
refreshSpinner.hidesWhenStopped = YES;

[refreshHeaderView addSubview:refreshLabel];
[refreshHeaderView addSubview:refreshArrow];
[refreshHeaderView addSubview:refreshSpinner];
[self.tableView addSubview:refreshHeaderView];

}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
if (isLoading) return;
isDragging = YES;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (isLoading) {

    if (scrollView.contentOffset.y > 0)
        self.tableView.contentInset = UIEdgeInsetsZero;
    else if (scrollView.contentOffset.y >= -REFRESH_HEADER_HEIGHT)
        self.tableView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
} else if (isDragging && scrollView.contentOffset.y < 0) {

    [UIView beginAnimations:nil context:NULL];
    if (scrollView.contentOffset.y < -REFRESH_HEADER_HEIGHT) {

        refreshLabel.text = self.textRelease;
    } else { 
        refreshLabel.text = self.textPull;
    }
    [UIView commitAnimations];
}
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (isLoading) return;
isDragging = NO;
if (scrollView.contentOffset.y <= -REFRESH_HEADER_HEIGHT)
{
    [self startLoading];
}
}

- (void)startLoading {
isLoading = YES;

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
self.tableView.contentInset = UIEdgeInsetsMake(REFRESH_HEADER_HEIGHT, 0, 0, 0);
refreshLabel.text = self.textLoading;
refreshArrow.hidden = YES;
[refreshSpinner startAnimating];
[UIView commitAnimations];

[self refresh];
}

- (void)stopLoading {
isLoading = NO;

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDidStopSelector:@selector(stopLoadingComplete:finished:context:)];
self.tableView.contentInset = UIEdgeInsetsZero;
UIEdgeInsets tableContentInset = self.tableView.contentInset;
tableContentInset.top = 0.0;
self.tableView.contentInset = tableContentInset;
[UIView commitAnimations];
}

- (void)stopLoadingComplete:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {

refreshLabel.text = self.textPull;
refreshArrow.hidden = NO;
[refreshSpinner stopAnimating];

}

- (void)refresh {

[self fetchTweets];

[self performSelector:@selector(stopLoading) withObject:nil afterDelay:2.7];
}


#pragma mark - Table view delegate

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"tweetVC"])
{
    NSInteger row = [[self tableView].indexPathForSelectedRow row];
    NSDictionary *tweet = [tweets objectAtIndex:row];

    TweetVC *tweetVC = segue.destinationViewController;
    tweetVC.detailItem = tweet;
}
}
Was it helpful?

Solution

After a lot of investigation I found an article somewhere that said there is a difference between the text key and the retweeted_status.text key. The tweets being truncated were, in fact, retweets from the user using the text key. However, the retweeted_status.text key is only the tweet that was retweeted, without the user who originally tweeted it. That sucks because the retweeted_status.text key is NOT truncated. Ahhh, the joys of programming. Hopefully the new twitter API will address this. I hope this answer helps somebody.

Here is the link to what I found in case anyone is interested: http://code.google.com/p/twitter-api/issues/detail?id=2261

OTHER TIPS

I haven't gone through your code, but I thought of mentioning this point that Twitter only allows tweet 140 characters long! This is the basic rule of a tweet. So no matter what you do tweet with mode than 140 characters will be truncated.

I hope this is not the issue?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top