TWTweetComposeViewController freezes my app completely on alloc-init - iphone

I've got an iPhone app that uses the Twitter framework in iOS 5. I've noticed that when I try to tweet something, the app completely freezes on the "alloc init" line of code.
Here's my code. Anybody see something wrong with it?
-(void)tweet {
NSLog(#"Tweeting");
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
if (stringToShare.length < 140) {
TWTweetComposeViewController *tweetController = [[TWTweetComposeViewController alloc] init];
[tweetController setInitialText:stringToShare];
[self presentModalViewController:tweetController animated:YES];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Easy there, Hemingway." message:[NSString stringWithFormat:#"Your note has %d characters, which exceeds Twitter's limit of 140.", stringToShare.length]delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
}
UPDATE: This method is called from a modal view controller. Could that be the issue?
UPDATE 2: Here's the line of code that's used to detect if the user can tweet:
if ([TWTweetComposeViewController canSendTweet]) {
[availableActions addObject:#"Tweet"];
}
I know that the issue is not constant --- it seems to occur on my phone, but not my co-founder's.

Related

Social sharing url of current webview iPhone. ( Xcode)

so I have my app setup with share action button that shares the current URL to Twitter or Facebook however when I click the Facebook button it shows a Twiiter share sheet. The (Tiwtter option works fine)
After I click the FACEBOOK option, when testing on iPhone the standard twiiter share sheet appears.
- (IBAction)social:(id)sender {
UIActionSheet *share = [[UIActionSheet alloc] initWithTitle:#"Pass on the news!" delegate:self cancelButtonTitle:#"OK" destructiveButtonTitle:nil otherButtonTitles:#"Post to Twitter", #"Post to Facebook", nil];
//You must show the action sheet for the user to see it.
[share showInView:self.view];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
//Each button title we gave to our action sheet is given a tag starting with 0.
if (actionSheet.tag == 0) {
//Check Twitter accessibility and at least one account is setup.
if([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) {
SLComposeViewController *tweetSheet =[SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
[tweetSheet addURL:self.newsItemWebView.request.URL]; //This is setting the initial text for our share card.
[tweetSheet setInitialText:#"Check out this article I found using the 'Pass' iPhone app:, "];
//Brings up the little share card with the test we have pre defind.
[self presentViewController:tweetSheet animated:YES completion:nil];
} else {
//This alreat tells the user that they can't use built in socal interegration and why they can't.
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Sorry" message:#"You can't send a tweet right now, make sure you have at least one Twitter account setup and your device is using iOS6 or above!." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
} else if (actionSheet.tag == 1) {
//Check Facebook accessibility and at least one account is setup.
if([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
SLComposeViewController *facebookSheet =[SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[facebookSheet addURL:self.newsItemWebView.request.URL];
//This is setting the initial text for our share card.
[facebookSheet setInitialText:#"Check out this article I found using the 'Pass' iPhone app:"];
//Brings up the little share card with the test we have pre defind.
[self presentViewController:facebookSheet animated:YES completion:nil];
} else {
//This alreat tells the user that they can't use built in socal interegration and why they can't.
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Sorry" message:#"You can't post a Facebook post right now, make sure you have at least one Facebook account setup and your device is using iOS6 or above!." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
}
}
You are using actionSheet.tag which will be the same for the entiere actionsheet.
If you want to know which button is pressed you should use buttonIndex in your if statements.
Even better is to use UIActivityViewController.
NSArray *items = #[self.newsItemWebView.request.URL];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
activityViewController.completionHandler = ^(NSString *activityType, BOOL completed) {
// do any thing you want when the user finishes the share activity.
// Like present a message that that activity has completed or not.
};
[self presentViewController:activityViewController animated:YES completion:nil];

how to display tweet after it was sent?

I'm working on a twitter app and i want to immediately display tweet after sending. I tried to use reloadData, but it didn't work. Can anyone help me? Thank you!
Here's my code:
- (IBAction)postNewTweet:(id)sender {
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
SLComposeViewController *tweetSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
[tweetSheet setInitialText:#""];
[self presentViewController:tweetSheet animated:YES completion:nil];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tweetTableView reloadData];
});
}
else
{
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:#"Sorry"
message:#"You can't send a tweet right now, make sure your device has an internet connection and you have at least one Twitter account setup"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}
Blaze, you are reloading the table view right after presenting the compose sheet, so it reload the table right there - and you are passing the completion block as nil, so nothing will happen when user finishes tweeting.
Also, you need to be sure that you are reloading not only the table, but the array or any other object that is the source of tweetTableView.
For example:
When calling the tweet compose sheet:
[self presentViewController:tweetSheet animated:YES completion:^(SLComposeViewControllerResult result)
{
dispatch_async(dispatch_get_main_queue(), ^{
[self reloadTweets];
});
}];
And then, you reload the tweets source and only then the table
-(void)reloadTweets
{
tweetsArray = .... //load the tweets from the internet, and only then reload the table
[self.tweetTableView reloadData];
}

UIAlertViewDelegate not acting as expected

I have a very simple process running where after each round of a simple game the scores are calculated, labels updated and all the normal, very simple stuff. I have a UIAlertView that informs the player of how s/he performed. I use a UIAlertViewDelegate to postpone all the updates, resetting of controls etc. till after the UIAlertView is dismissed. The methods are [startNewRound],[startOver] and [updateLabels]. It's fairly obvious what they all do. Anyway, when the user hits round ten, I've made another UIAlertView that informs the player that the game has ended and shows the overall score. Again, I hoped to use a delegate to postpone the resets till after the AlertView is dismissed. The only problem is, with the endGame AlertView, it seems to be using the first AlertView's delegate method causing the game to continue with a new round and not start from the beginning. I hope this makes sense. Anyway, here are snippets of my code.
if (round == 10){
UIAlertView *endGame = [[UIAlertView alloc]
initWithTitle: #"End of Game"
message: endMessage
delegate:self
cancelButtonTitle:#"New Game"
otherButtonTitles:nil];
[endGame show];
}
else {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle: title
message: message
delegate:self
cancelButtonTitle:#"Next"
otherButtonTitles:nil];
[alertView show];
}
And then the delegate methods:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
[self startNewRound];
[self updateLabels];
}
- (void)endGame:(UIAlertView *)endGame didDismissWithButtonIndex:(NSInteger)buttonIndex
{
[self startOver];
}
So there it is. As I mentioned, the endGame AlertView appears to be using alertView's delegate, thus not activating the [self startOver] method. All the methods are working, it's just the AlertView is using the incorrect delegate method. Regards, Mike
Change your code like this,
if (round == 10){
UIAlertView *endGame = [[UIAlertView alloc]
initWithTitle: #"End of Game"
message: endMessage
delegate:self
cancelButtonTitle:#"New Game"
otherButtonTitles:nil];
endGame.tag = 111;
[endGame show];
}
else {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle: title
message: message
delegate:self
cancelButtonTitle:#"Next"
otherButtonTitles:nil];
alertView.tag = 222;
[alertView show];
}
and delegate method as,
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if(alertView.tag == 111)
{
[self startNewRound];
[self updateLabels];
}
else if(alertView.tag == 222)
{
[self startOver];
}
}
You cant have two delegate method for dismisswithbuttonindex, you need to handle this situation with tag.
Give both alert view a different tag and check it on delegate object. Thus you can differentiat the both alert view.

Add Text in TweetSheet when an UIAlert is pressed

Can anyone tell me how i can add text in TweetSheet when an UIAlert Title button is pressed?
Currently i am using this code to achieve it, but failed so far.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
TWTweetComposeViewController *tweetSheet = [[TWTweetComposeViewController alloc] init];
if ([title isEqualToString:#"Add custom text"]) {
UIAlertView *alert= [[UIAlertView alloc] initWithTitle:#"Add a template" message:nil delegate:self cancelButtonTitle:#"Hi it was nice meeting you" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
if ([title isEqualToString:#"Hi it was nice meeting you"]) {
[tweetSheet setInitialText:#"hey it was nice meeting you"];
}
}
Can anyone tell me what's wrong here?
You're not presenting your TWTweetComposeViewController you can do this simply by adding :
[self presentModalViewController:tweetSheet animated:YES];
I guess this code is only for a simple test tweet.
For a serious project you should always:
Check if the user can send tweets by calling +(BOOL)canSendTweet before trying to show the TWTweetComposeViewController
If not sure about the properties you'll be setting (text, images, urls), you need to check if adding them was successful : -(BOOL)addImage:(UIImage *)image, -(BOOL)addURL:(NSURL *)url and -(BOOL)setInitialText:(NSString *)text all return YES if it was successful and NO if not.
You can set a completion handler to perform different actions depending on what the user decided (send tweet/cancel)
The WWDC session about Twitter integration from 2011 is very simple and detailed, you should watch it and read the documentation if you need more information.

Another "wait_fences: failed to receive reply" Question (UIAlertView)

There are a number of questions regarding the "wait_fences: failed to receive reply" on this forum already, but none of the proposed solutions work for me (although they did help me to mitigate it).
When my app starts up, I do a reachability check, and if I can't reach the host I'm looking for, I pop up a UIAlertView. Initially I was doing this before I even set up the view controller, but then I learned one of the causes of the "wait_fences" problem is that the responder chain isn't properly set up if you haven't displayed a view yet - so I moved everything down into -viewDidAppear. Basically, this is what I have:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Figure out what the reflections name is, then check to see if it can find it online;
// If it can't, -informUserSiteIsNotReachable is called, below
[self retrieveReflectionByName:self.todaysReflectionName];
[self displayReflectionByName:self.todaysReflectionName];
}
- (void)informUserSiteIsNotReachable
{
SEL messageSelector;
if (NO == [self internetIsReachable]) {
messageSelector = #selector(internetNotAccessible);
} else {
messageSelector = #selector(reflectionsSiteNotAccessible);
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[Strings alertViewTitleWhenSiteIsUnreachable] message:[Strings performSelector:messageSelector] delegate:self cancelButtonTitle:#"OK" otherButtonTitles:NULL];
[alert show];
[alert release];
}
I can't seem to get rid of the wait_fences problem: any suggestions?
Here I also faced the same problem in my projects and I solved the issue which is "wait_fences".
Here you can do one change in your code as follows:
- (void)informUserSiteIsNotReachable
{
SEL messageSelector;
if (NO == [self internetIsReachable]) {
messageSelector = #selector(internetNotAccessible);
} else {
messageSelector = #selector(reflectionsSiteNotAccessible);
}
[NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:#selector(Show_AlertMessage) userInfo:nil repeats:NO];
}
- (void) Show_AlertMessage
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[Strings alertViewTitleWhenSiteIsUnreachable] message:[Strings performSelector:messageSelector] delegate:self cancelButtonTitle:#"OK" otherButtonTitles:NULL];
[alert show];
[alert release];
}
This works for me. Hope you get rid of this wait_fences issue soon. Let me know if you still have the problem.