TableView Cell tweets


#1

I have a timeline of tweets from a specific user.

TWTRTweet *tweet = self.tweetsArray[indexPath.row];
TWTRTweetTableViewCell *cell = (TWTRTweetTableViewCell *)[tableView dequeueReusableCellWithIdentifier:TweetTableReuseIdentifier forIndexPath:indexPath];

[cell configureWithTweet:tweet];
cell.tweetView.delegate = self;
cell.tweetView.showBorder = YES;

// cell.tweetView.style = TWTRTweetViewStyleRegular;

NSLog(@"%i", (int)cell.tweetView.style);

return cell;

The cells display fine except that the user cannot do anything with the tweets, i.e.
TWTRTweetViewStyle is COMPACT and TWTRTweetView is read-only on the cell.

It would be really helpful if the user could favorite or retweet or reply to - you know - else I gotta dump TwitterKit from my app and go back to SLRequest.

I am familiar with this:
Tweet View Style
There are two different styles for Tweet views: TWTRTweetViewStyleRegular and TWTRTweetViewStyleCompact. Regular Tweet views show large images and have a “Share Tweet” button, whereas compact Tweet views are designed to be put inside tableviews through the TWTRTweetTableViewCell (see Show a UITableView of Tweets ).

So I have to send it out to a detail view controller with a single view? And where does it go from there? Twitter app? Documentation is a little skinny in this area. Any help?


#2

The TWTRTweetTableViewCell only works with the compact tweet view style. As you know there aren’t any actions on these tweet views for the time being.

If you need actions I would suggest creating your own UITableViewCell that holds a TWTRTweetView plus some room at the bottom for your own buttons.


#3

Hi. A couple of users on here (including me) have been struggling to get a table view in Swift to display a timeline of tweets from a specific user. I have only been able to complete a table with a timeline of individual tweet ID’s rather than tweets for a specific user. As you elude to having successfully done this for a specific user, could you please show your complete code upto the point you ask for help in this post. Many thanks


#4

I understand your struggle intimately. What a pain it was back in the day. I’ll give it a try - I hope I don’t mess up the code formatting. My code is in Objective-C. Hopefully you will understand that I do not have time to translate into Swift for you. This should give you an idea of how to grab the individual tweets from the user.

AS you may be able to see, I used good old fashioned SLRequest a lot.

I have a ViewController called TweetsListViewController with an embedded UITableView as opposed to a TableViewController. I wanted a nice profile header at the top.

In viewDidLoad I call [self loadTwitterData];

- (void)loadTwitterData {
    self.startRefreshDate = [NSDate date];
    [self getTwitterProfile];
    [self refreshTwitterFeed];
    [self getTwitterUserID];
}

The TwitterProfileView has the app’s twitter account images, follower count, following count and a follow/unfollow button above the tableview of tweets. I need the TwitterUserID to see if the user is following the app to present the correct button and the correct follow button action - follow/unfollow. It’s kind of miss mash - I’ll clean it up later

startRefreshDate is for refreshControl using ISRefreshControl library

- (void)refreshTwitterFeed {
    // check connection
    if (![self checkTwitterService]) return;
    
    __weak typeof(self)weakSelf = self;
    [self.twitterAdapter refreshTwitterFeedWithCompletion:^(NSArray* jsonResponse) {
        [weakSelf twitterFeedRefreshed:jsonResponse];
    }];
}

- (void)twitterFeedRefreshed:(NSArray *)jsonResponse {
    self.tweetsArray = jsonResponse;
    [self.tweetsTableView reloadData];
    
    NSTimeInterval interval = [[NSDate date] timeIntervalSinceDate:_startRefreshDate];
    NSTimeInterval minimumInterval = 3;
    
    if (interval > minimumInterval) {
        [self.refreshControl endRefreshing];
    } else {
        [self.refreshControl performSelector:@selector(endRefreshing) withObject:nil afterDelay:(minimumInterval - interval)];
    }
}

- (void)getTwitterProfile {
    // check connection
    if (![self checkTwitterService]) return;
    
    __weak typeof(self)weakSelf = self;
    [self.twitterAdapter getTwitterProfileWithCompletion:^(NSDictionary* jsonResponse) {
        [weakSelf twitterProfileReceived:jsonResponse];
    }];
}

-(void)twitterProfileReceived:(NSDictionary*)jsonResponse{
    
    self.twitterAdapter.profile = [[TwitterProfile alloc] initWithJSON:jsonResponse];
    
    [_profileView.usernameLabel setText:self.twitterAdapter.profile.name];
    [_profileView.followerCountLabel setText:[self.twitterAdapter.profile.followerCount stringValue]];
    [_profileView.followingCountLabel setText:[self.twitterAdapter.profile.followingCount stringValue]];
    [_profileView.screenNameLabel setText:[NSString stringWithFormat:@"@%@", self.twitterAdapter.profile.screenName]];
    
    if (self.imagesDictionary[kTwitterProfileImageKey]) {
        _profileView.profilePictureImageView.image = self.imagesDictionary[kTwitterProfileImageKey];
    } else {
        [self getImageFromUrl:self.twitterAdapter.profile.profileImageUrl asynchronouslyForImageView:_profileView.profilePictureImageView andKey:kTwitterProfileImageKey];
        
        [self getImageFromUrl:self.twitterAdapter.profile.profileBannerUrl asynchronouslyForImageView:_profileView.bannerImageView andKey:kTwitterBannerImageKey];
    }
}

My TwitterAdapter is an NSObject Helper to consolidate Twitter calls some. TwitterProfile is just a NSObject data model

Header file:

#import <Foundation/Foundation.h>

@import Accounts;
@import Social;

#define AccountTwitterAccessGranted @"TwitterAccessGranted"
#define AccountTwitterSelectedIdentifier @"TwitterAccountSelectedIdentifier"

typedef enum {
    TwitterRequestTypeFollow = 0,
    TwitterRequestTypeUnFollow = 1,
    TwitterRequestTypeFollowersList = 2,
    TwitterRequestTypeTwitterUserID = 3
} TwitterRequestType;

@class TwitterProfile;

@interface TwitterAdapter : NSObject

@property (nonatomic, strong) ACAccount* account;
@property (nonatomic, strong) NSString *screenName;
@property (nonatomic, strong) NSString *userIdString;

@property (nonatomic, strong) TwitterProfile *profile;


- (void)accessTwitterAccountWithAccountStore:(ACAccountStore*)accountStore;
- (void)refreshTwitterFeedWithCompletion:(void (^)(NSArray* jsonResponse))completion;
- (void)getTwitterProfileWithCompletion:(void (^)(NSDictionary* jsonResponse))completion;

-(void)performTwitterRequest:(TwitterRequestType)twitterRequestType
              withParameters:(NSDictionary *)params
               andCompletion:(void (^)(NSDictionary *resultsDictionary))completion;

Implementation File:

#import "TwitterAdapter.h"
#import "AppDelegate.h"
#import "TwitterProfile.h"


#import <TwitterKit/TwitterKit.h>

#define API_TWITTER_FOLLOW @"https://api.twitter.com/1.1/friendships/create.json"
#define API_TWITTER_UNFOLLOW @"https://api.twitter.com/1.1/friendships/destroy.json"
#define API_TWITTER_FOLLOWERS_LIST @"https://api.twitter.com/1.1/followers/ids.json"
#define API_TWITTER_USER_ID @"https://api.twitter.com/1.1/users/show.json"


@interface TwitterAdapter ()

@property (strong, nonatomic) ACAccountStore *accountStore;

-(NSURL *)urlForTwitterRequest:(TwitterRequestType)twitterRequestType;
-(NSDictionary *)parametersForTwitterRequest:(TwitterRequestType)twitterRequestType;

-(void)startNetworkSpinner;
-(void)stopNetworkSpinner;

@end


@implementation TwitterAdapter

#pragma mark - Access AccountStore

-(void)accessTwitterAccountWithAccountStore:(ACAccountStore*)store{
    [self startNetworkSpinner];
    
    self.accountStore = store;
    ACAccountType *twitterAccountType = [self.accountStore
                                         accountTypeWithAccountTypeIdentifier:
                                         ACAccountTypeIdentifierTwitter];
    
    __weak typeof(self)weakSelf = self;
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self.accountStore
         requestAccessToAccountsWithType:twitterAccountType
         options:nil completion:^(BOOL granted, NSError *error) {
             if (granted) {
                 NSArray *twitterAccounts = [weakSelf.accountStore accountsWithAccountType:twitterAccountType];
                 NSString *twitterAccountIdentifier = [[NSUserDefaults standardUserDefaults] objectForKey:AccountTwitterSelectedIdentifier];
                 
                 weakSelf.account = [weakSelf.accountStore accountWithIdentifier:twitterAccountIdentifier];
                 
                 if (weakSelf.account) {
                     dispatch_async(dispatch_get_main_queue(), ^{
                         [[NSNotificationCenter defaultCenter] postNotificationName:AccountTwitterAccessGranted
                                                                             object:nil];
                     });
                 } else {
                     [[NSUserDefaults standardUserDefaults] removeObjectForKey:AccountTwitterSelectedIdentifier];
                     [[NSUserDefaults standardUserDefaults] synchronize];
                     
                     if (twitterAccounts.count > 1) {
                         UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Select an account"
                                                                             message:@"Please choose one of your Twitter accounts"
                                                                            delegate:self
                                                                   cancelButtonTitle:@"Cancel"
                                                                   otherButtonTitles:nil];
                         
                         for (ACAccount *account in twitterAccounts) {
                             [alertView addButtonWithTitle:account.accountDescription];
                         }
                         
                         dispatch_async(dispatch_get_main_queue(), ^{
                            [alertView show];
                         });
                     } else {
                         weakSelf.account = [twitterAccounts lastObject];
                         dispatch_async(dispatch_get_main_queue(), ^{
                            [[NSNotificationCenter defaultCenter] postNotificationName:AccountTwitterAccessGranted
                                                                                object:nil];
                         });
                     }
                 }
             } else {
                 if (error) {
                     dispatch_async(dispatch_get_main_queue(), ^{
                         UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Twitter Error"
                                                                             message:@"Please make sure you have a Twitter account set up in Settings. Also grant access to this app"
                                                                            delegate:nil
                                                                   cancelButtonTitle:@"Dismiss"
                                                                   otherButtonTitles:nil];
                         [alertView show];
                     });
                 } else {
                     dispatch_async(dispatch_get_main_queue(), ^{
                         UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Twitter Error"
                                                                             message:@"We can't access Twitter, please add an account in the Settings app"
                                                                            delegate:nil
                                                                   cancelButtonTitle:@"Dimiss"
                                                                   otherButtonTitles:nil];
                         [alertView show];
                     });
                 }
             }
             
             [weakSelf stopNetworkSpinner];
         }];
    });
}

#pragma mark - Twitter Feed

- (void)refreshTwitterFeedWithCompletion:(void (^)(NSArray* jsonResponse))completion {
    if(!self.account){
        ACAccountStore* store = [AppDelegate sharedInstance].accountStore;
        [self accessTwitterAccountWithAccountStore:store];
        return;
    }

    __weak typeof(self)weakSelf = self;
    [self startNetworkSpinner];
    
    NSURL* url = [NSURL URLWithString:@"https://api.twitter.com/1.1/statuses/user_timeline.json"];
    NSDictionary* params = @{@"count" : @"50", @"screen_name" : self.screenName};
    
    SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter
                                            requestMethod:SLRequestMethodGET
                                                      URL:url
                                               parameters:params];
    
    request.account = self.account;
    
    [request performRequestWithHandler:^(NSData *responseData,
                                         NSHTTPURLResponse *urlResponse, NSError *error) {
        if (error) {
            NSString* errorMessage = [NSString stringWithFormat:@"There was an error reading Twitter feed. %@",
                                      [error localizedDescription]];
            
            [[AppDelegate sharedInstance] showError:errorMessage];
        } else {
            NSError *jsonError;
            NSArray *responseJSON = [NSJSONSerialization JSONObjectWithData:responseData
                                                                    options:NSJSONReadingAllowFragments
                                                                      error:&jsonError];
            
            NSMutableArray *tweets = nil;
            if (responseJSON.count > 0) {
                tweets = [[NSMutableArray alloc] init];
                
                for (NSDictionary *jsonDict in responseJSON) {
                    TWTRTweet *tweet = [[TWTRTweet alloc] initWithJSONDictionary:jsonDict];
                    [tweets addObject:tweet];
                }
            }
            
            if (jsonError) {
                NSString* errorMessage = [NSString stringWithFormat:@"There was an error reading your Twitter feed. %@",
                                          [jsonError localizedDescription]];
                
                [[AppDelegate sharedInstance] showError:errorMessage];
            } else {
                dispatch_async(dispatch_get_main_queue(), ^{
                    if(completion){
                        completion(tweets);
                    }
                });
            }
        }
        
        [weakSelf stopNetworkSpinner];
    }];
}

#pragma mark - Twitter Profile

- (void)getTwitterProfileWithCompletion:(void (^)(NSDictionary* jsonResponse))completion {
    
    if(!self.account){
        ACAccountStore* store = [AppDelegate sharedInstance].accountStore;
        [self accessTwitterAccountWithAccountStore:store];
        return;
    }
    
    __weak typeof(self)weakSelf = self;
    [self startNetworkSpinner];

    NSURL* url = [NSURL URLWithString:@"https://api.twitter.com/1.1/users/show.json"];
    NSDictionary* params = @{@"screen_name" : self.screenName};
    
    SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter
                                            requestMethod:SLRequestMethodGET
                                                      URL:url parameters:params];
    
    request.account = self.account;
    
    [request performRequestWithHandler:^(NSData *responseData,
                                         NSHTTPURLResponse *urlResponse, NSError *error) {
        if (error) {
            NSString* errorMessage = [NSString stringWithFormat:@"There was an error reading Twitter feed. %@",
                                      [error localizedDescription]];
            
            [[AppDelegate sharedInstance] showError:errorMessage];
        } else {
            NSError *jsonError;
            NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:responseData
                                                                         options:NSJSONReadingMutableLeaves
                                                                           error:&jsonError];
            
            if (jsonError) {
                NSString* errorMessage = [NSString stringWithFormat:@"There was an error reading Twitter feed. %@",
                                          [jsonError localizedDescription]];
                
                [[AppDelegate sharedInstance] showError:errorMessage];
            } else {
                dispatch_async(dispatch_get_main_queue(), ^{
                    if(completion){
                        completion(responseJSON);
                    }
                });
            }
        }
        
        [weakSelf stopNetworkSpinner];
    }];
}

#pragma mark - AlertView for Acounts

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    if (buttonIndex != alertView.cancelButtonIndex) {
        ACAccountType *twitterAccountType = [self.accountStore accountTypeWithAccountTypeIdentifier:
                                             ACAccountTypeIdentifierTwitter];
        NSArray *twitterAccounts = [self.accountStore accountsWithAccountType:twitterAccountType];
        self.account = twitterAccounts[(buttonIndex - 1)];
        
        [[NSUserDefaults standardUserDefaults] setObject:self.account.identifier
                                                  forKey:AccountTwitterSelectedIdentifier];
        [[NSUserDefaults standardUserDefaults] synchronize];
        
        [[NSNotificationCenter defaultCenter] postNotificationName:AccountTwitterAccessGranted object:nil];
    }
}

#pragma mark - Twitter Request

- (void)performTwitterRequest:(TwitterRequestType)twitterRequestType withParameters:(NSDictionary *)params andCompletion:(void (^)(NSDictionary *))completion {
    
    if(!self.account){
        ACAccountStore *store = [AppDelegate sharedInstance].accountStore;
        [self accessTwitterAccountWithAccountStore:store];
        return;
    }
    
    __weak typeof(self)weakSelf = self;
    [self startNetworkSpinner];
    
    // set variables
    NSURL *requestUrl = [self urlForTwitterRequest:twitterRequestType];
    if (params == nil)
        params = [self parametersForTwitterRequest:twitterRequestType];
    
    // set request method
    SLRequestMethod requestMethod;
    if (twitterRequestType == TwitterRequestTypeFollowersList || twitterRequestType == TwitterRequestTypeTwitterUserID) {
        requestMethod = SLRequestMethodGET;
    } else {
        requestMethod = SLRequestMethodPOST;
    }
    
    // create request
    SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter
                                            requestMethod:requestMethod
                                                      URL:requestUrl
                                               parameters:params];
    request.account = self.account;
    
    // perform request
    [request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
        if (error) {
            NSString *errorMessage = @"There was an error with your Twitter request.";
            [[AppDelegate sharedInstance] showError:errorMessage];
        } else {
            NSError *jsonError = nil;
            NSDictionary *responseJSONDictionary = nil;
            NSString *errorMessage = nil;
            
            if (twitterRequestType == TwitterRequestTypeFollowersList || twitterRequestType == TwitterRequestTypeTwitterUserID) {
                NSArray *responseArray = [NSJSONSerialization JSONObjectWithData:responseData
                                                                         options:NSJSONReadingAllowFragments
                                                                           error:&jsonError];
                if (twitterRequestType == TwitterRequestTypeTwitterUserID) {
                    responseJSONDictionary = @{@"profile" : responseArray, @"twitterRequestType" : @(twitterRequestType)};
                } else {
                    responseJSONDictionary = @{@"statuses" : responseArray, @"twitterRequestType" : @(twitterRequestType)};
                }
                
                if (jsonError) {
                    errorMessage = @"There was an unknown error with Twitter.";
                    [[AppDelegate sharedInstance] showError:errorMessage];
                } else {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        if (completion)
                            completion(responseJSONDictionary);
                    });
                }
            } else {
                if ([urlResponse statusCode] == 200) {
                    NSLog(@"--->TWITTER REQUEST SUCCESS: %@", [urlResponse description]);
                } else {
                    NSLog(@"--->TWITTER REQUEST ERROR, HTTP response: %i", [urlResponse statusCode]);
                }
                
                NSNumber *statusCode = @([urlResponse statusCode]);
                NSDictionary *resultsDictionary = @{@"statusCode" : statusCode, @"twitterRequestType" : @(twitterRequestType)};
                
//                NSLog(@"-->status: %@", resultsDictionary);
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (completion)
                        completion(resultsDictionary);
                });
            }
        }
        
        [weakSelf stopNetworkSpinner];
    }];
}

#pragma mark - Helper Methods

- (NSURL *)urlForTwitterRequest:(TwitterRequestType)twitterRequestType {
    NSURL *url = nil;

    switch (twitterRequestType) {
        case TwitterRequestTypeFollow:
            url = [NSURL URLWithString:API_TWITTER_FOLLOW];
            break;
            
        case TwitterRequestTypeUnFollow:
            url = [NSURL URLWithString:API_TWITTER_UNFOLLOW];
            break;
            
        case TwitterRequestTypeFollowersList:
            url = [NSURL URLWithString:API_TWITTER_FOLLOWERS_LIST];
            break;
            
        case TwitterRequestTypeTwitterUserID:
            url = [NSURL URLWithString:API_TWITTER_USER_ID];
            break;
    }
    
    return url;
}

- (NSDictionary *)parametersForTwitterRequest:(TwitterRequestType)twitterRequestType {
    NSDictionary *params = nil;

    switch (twitterRequestType) {
        case TwitterRequestTypeFollow:
            params = @{@"screen_name" : self.screenName, @"follow" : @"true"};
            break;
            
        case TwitterRequestTypeUnFollow:
            params = @{@"screen_name" : self.screenName};
            break;
            
        case TwitterRequestTypeFollowersList:
            params = @{@"screen_name" : self.screenName, @"skip_status" : @"1", @"count" : @"5000", @"include_user_entities" : @"0", @"stringify_ids" : @"1"};
            break;
            
        case TwitterRequestTypeTwitterUserID:
            params = @{@"screen_name" : self.account.username};
            break;
    }
    
    return params;
}

#pragma mark - Network Spinners

- (void)startNetworkSpinner {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}

- (void)stopNetworkSpinner {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}

#pragma mark - Getters

- (NSString *)screenName {
    if (!_screenName)
        self.screenName = kAppTwitterScreenName;
    
    return _screenName;
}

@end

Back to TweetsListViewController

- (void)getTwitterUserID {
    // check connection
    if (![self checkTwitterService]) return;
    
    __weak typeof(self)weakSelf = self;

    [self.twitterAdapter performTwitterRequest:TwitterRequestTypeTwitterUserID
                           withParameters:nil
                            andCompletion:
     ^(NSDictionary *resultsDictionary) {
         weakSelf.twitterAdapter.userIdString = resultsDictionary[@"profile"][@"id_str"];
         [weakSelf getFollowersList];
     }];
}

- (void)getFollowersList {
    // check connection
    if (![self checkTwitterService]) return;
    
    __weak typeof(self)weakSelf = self;
    
    [self.twitterAdapter performTwitterRequest:TwitterRequestTypeFollowersList
                                withParameters:nil
                                 andCompletion:
     ^(NSDictionary *resultsDictionary) {
         NSArray *usersArray = resultsDictionary[@"statuses"][@"ids"];
         
         BOOL idMatch = NO;
         for (NSString *followerID in usersArray) {
             if ([followerID isEqualToString:weakSelf.twitterAdapter.userIdString]) {
                 NSLog(@"------>MATCH!!! => isFollowing = %d", weakSelf.twitterAdapter.profile.isFollowing);
                 idMatch = YES;
                 break;
             }
         }
         
         weakSelf.twitterAdapter.profile.isFollowing = idMatch;
         NSLog(@"------>isFollowing = %d", weakSelf.twitterAdapter.profile.isFollowing);
         [weakSelf configureFollowButton:weakSelf.twitterAdapter.profile.isFollowing];
    }];
}

- (IBAction)followMeButtonPressed:(id)sender {
    if (self.twitterAdapter.profile.isFollowing) {
        __weak typeof(self)weakSelf = self;
        
        NSString *message = [NSString stringWithFormat:@"Are you sure you wish to Un-Follow @%@?", self.twitterAdapter.screenName];
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Twitter"
                                                                       message:message
                                                                preferredStyle:UIAlertControllerStyleAlert];
        
        UIAlertAction *action = [UIAlertAction actionWithTitle:@"Yes"
                                                         style:UIAlertActionStyleDefault
                                                       handler:^(UIAlertAction *action) {
                                                           [weakSelf processFollowRequest];
                                                       }];
        
        UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"No"
                                                         style:UIAlertActionStyleCancel
                                                       handler:nil];
        
        [alert addAction:action];
        [alert addAction:cancel];
        
        [self presentViewController:alert animated:YES completion:nil];
    } else {
        [self processFollowRequest];
    }
}

- (void)processFollowRequest {
    // check connection
    if (![self checkTwitterService]) return;
    
    __weak typeof(self)weakSelf = self;
    
    TwitterRequestType followTwitterRequest = TwitterRequestTypeFollow;
    if (self.twitterAdapter.profile.isFollowing)
        followTwitterRequest = TwitterRequestTypeUnFollow;
    
    [self.twitterAdapter performTwitterRequest:followTwitterRequest
                                withParameters:nil
                                 andCompletion:
     ^(NSDictionary *resultsDictionary) {
         NSString *statusCode = [resultsDictionary[@"statusCode"] stringValue];
         
         if ([statusCode isEqualToString:@"200"]) {
             NSLog(@"--->SUCCESS FOLLOW - UNFOLLOW | STATUSCODE = %d@", statusCode);
             weakSelf.twitterAdapter.profile.isFollowing = !weakSelf.twitterAdapter.profile.isFollowing;
             [weakSelf getTwitterProfile];
             [weakSelf configureFollowButton:weakSelf.twitterAdapter.profile.isFollowing];
         } else {
             NSString *failureMessage = nil;
             NSString *title = @"Twitter";
             
             if (followTwitterRequest == TwitterRequestTypeFollow)
                 failureMessage = [NSString stringWithFormat:@"There was an Error trying to follow %@.", weakSelf.twitterAdapter.screenName];
             else if (followTwitterRequest == TwitterRequestTypeUnFollow)
                 failureMessage = [NSString stringWithFormat:@"There was an Error trying to un-follow %@.", weakSelf.twitterAdapter.screenName];
             
             [weakSelf showAlertWithMessage:failureMessage andTitle:title];
         }
     }];
}

#5

Hey Ben, the team recently shipped support for Timelines. Take a look at the following doc: https://dev.twitter.com/twitter-kit/ios/show-timelines


#6

Does the same apply if we push the timeline tweet to another view controller? Upon selecting a tweet from a timeline I create a view controller and push it onto my navigation controller:

- (void)tweetView:(TWTRTweetView *)tweetView didSelectTweet:(TWTRTweet *)tweet
{    
    UIViewController* tweetViewController = [[UIViewController alloc] init];
    TWTRTweetView* customView = [[TWTRTweetView alloc] initWithTweet:tweet style:TWTRTweetViewStyleRegular];
    tweetViewController.view = customView;
    [self.navigationController pushViewController:tweetViewController animated:YES];
    tweetViewController.edgesForExtendedLayout = UIRectEdgeNone;
    }

This provides me with a tweet view that has a TWTRTweetViewStyleRegular style, and consequently shows the ‘Share Tweet’ button. Would I still need to create my own buttons/implementations for retweet/favorite/follow functionality? Is there no easier way to achieve this?

Edit: added tweetViewController.edgesForExtendedLayout = UIRectEdgeNone; to prevent tweet extending under the navigation bar.


#7

dpAudio: You are correct. There is currently no other way to use Retweet/Favorite/Follow apart from creating your own buttons.

I like your idea of pushing a regular style tweet view in a new view controller though! That’s slick.


#8

stevenhepting: thanks for confirming. It would be pretty sweet if there was an API to have all those buttons pop up automatically.

I like your idea of pushing a regular style tweet view in a new view controller though! That’s slick.

Thanks for the feedback, man! It’s working out ok:

However when I do that for a retweet, the retweet icon gets stretched out:

Guess I’ll have to dig into how the TWTRTweetView is being displayed. If you have any suggestions off the top of your head it would be much appreciated!


#9

I would just set the width to be full-screen and then allow the height to be whatever is returned from the sizeThatFits: method.


#10

Thanks again, stevenhepting. I wrestled with a few different ways of trying to display tweets from a timeline (including using the sizeThatFits: method) but I kept running into display issues.

For anyone that’s interested, I ended up settling on the following, which includes using a background image over which the selected tweets appear:

- (void)tweetView:(TWTRTweetView *)tweetView didSelectTweet:(TWTRTweet *)tweet
{
    static const float kTweetOriginX = 0.0;
    static const float kTweetOriginY = 0.0;
    static const float kTweetWidth   = 300.0;
    static const float kTweetHeightAdjustment = 100.0;
    const  float       kTweetHeight  = self.view.frame.size.height - self.navigationController.navigationBar.frame.size.height - kTweetHeightAdjustment;
    
    UIViewController* tweetViewController = [[UIViewController alloc] init];
    
    TWTRTweetView* customView = [[TWTRTweetView alloc] initWithTweet:tweet style:TWTRTweetViewStyleRegular];
    customView.showBorder = NO;
    
    if (customView.frame.size.height > self.view.frame.size.height )
    {
        customView.frame = CGRectMake(kTweetOriginX, kTweetOriginY, kTweetWidth, kTweetHeight);
    }

    UIImageView *backgroundImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Background.png"]];
    
    tweetViewController.view = backgroundImage;
    tweetViewController.view.contentMode = UIViewContentModeScaleAspectFit;
    tweetViewController.view.userInteractionEnabled = YES;
    [tweetViewController.view addSubview:customView];

    customView.center = self.view.center;

    [self.navigationController pushViewController:tweetViewController animated:YES];
}

#11