Say you want to do something once user finish. What do you do?
It doesn't have a delegate. What to do once a present view controller is dismissed?
In the Apple documentation you'll find that SLComposeViewController has a completion handler property instead of a delegate. You just need to set that property using the setCompletionHandler method. Then you use the constant SLComposeViewControllerResult to recover whether the post was posted or canceled and take action accordingly.
-(void) shareToFacebook {
//1. Set link and image
NSString *appLink = #"https://itunes.apple.com/app/id989793966";
UIImage *twitterImage = [UIImage imageNamed:#"TF_400x400.png"];
//2. Check if we can share
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
//3. Compose the share view controller
SLComposeViewController *FBViewController = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[FBViewController addURL:[NSURL URLWithString:appLink]];
[FBViewController addImage:twitterImage];
//4 Set completion handler and define actions to take
[FBViewController setCompletionHandler:^(SLComposeViewControllerResult result)
{
if (result == SLComposeViewControllerResultCancelled) {
[self addEmptyScreenButtonTargets];
} else if (result == SLComposeViewControllerResultDone) {
//Unlock words; show thank you screen
[NewCardManager unlockWordsForPackage:4];
[self openFBThankYouScreen];
}
}];
//5. Call to modally present the share controller
[self presentViewController:FBViewController animated:YES completion:nil];
}
}
Related
In my app I am using TTOpenInAppActivity to insert "Open in" action inside UIActivityController.
Inside it works like this:
Some view controller presents UIActivityController with TTOpenInActivity already built in.
-(void)openWithAction
{
NSURL *fileURL = SOME_URL;
CGRect rect = SOME_RECT;
TTOpenInAppActivity *openInAppActivity = [[TTOpenInAppActivity alloc] initWithView:self.view andRect:rect];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[fileURL] applicationActivities:#[openInAppActivity]];
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
// Store reference to superview (UIActionSheet) to allow dismissal
openInAppActivity.superViewController = activityViewController;
// Show UIActivityViewController
[self presentViewController:activityViewController animated:YES completion:NULL];
} else {
// code for iPad, irrelevant
}
}
When user taps "Open in" button, the following method is triggered:
- (void)performActivity
{
if(!self.superViewController){
[self activityDidFinish:YES];
return;
}
// Dismiss activity view
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
// iPhone dismiss UIActivityViewController
[self.superViewController dismissViewControllerAnimated:YES completion:^(void){
if (self.fileURLs.count > 1) {
[self openSelectFileActionSheet];
}
else {
// Open UIDocumentInteractionController
[self openDocumentInteractionControllerWithFileURL:self.fileURLs.lastObject];
}
}];
} else {
// code for iPad, irrelevant
}
}
}
As the app is for iPhone only, this piece of code should be executed:
[self.superViewController dismissViewControllerAnimated:YES completion:^(void){
if (self.fileURLs.count > 1) {
[self openSelectFileActionSheet];
}
else {
// Open UIDocumentInteractionController
[self openDocumentInteractionControllerWithFileURL:self.fileURLs.lastObject];
}
}];
In iOS7 everything works fine. In iOS8 UIActivityController is dismissed and then nothing happens.
While debugging I did manage to detect that in iOS8 completion handler is never called.
Please, help me find out the reason for this behavior and make it work as it should.
Thank you in advance.
In iOS 8, when you tap on "Open in", UIActivityViewController is dismissed automatically. So, when you call self.superViewController dismissViewControllerAnimated:completion:, viewController was already dismissed and method do nothing (so completion not called).
What can I do if isAvailableForServiceType method returns NO in case of Twitter, for example?
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) {
// post message
} else {
// show some additional screen
}
Can I somehow provide the user a standard login / register view or switch him to the iOS settings? If yes, how can I do it?
Thanks in advance.
try this
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) {
//
} else {
SLComposeViewController *twitterSignInDialog = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
[self presentViewController:twitterSignInDialog animated:NO completion:nil];
}
i am new to objective C and im trying to make a share button for twitter in my game. Im using spritebuilder to create all my buttons and sprites. All of my code lies in MainScene.m while my code for twitter share sheet is in ShareViewController.m
In my MainScene.m file i have a method sendToController, which using an object of shareViewController calls a method postToTwitter which is in ShareViewController.m. Due to some reason this tweetsheet is not visbile and from what i gather is that there is a window heirachy problem which i am not able to solve.
Here is the code in MainScene.m
ShareViewController *_shareViewController;
#synthesize shareViewController;
(void)sendToController {
_shareViewController = [ShareViewController alloc];
[_shareViewController postToTwitter];
}
Here is the code for ShareViewController.m
#implementation ShareViewController {
MainScene *_mainSceneObj;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_mainSceneObj.ShareViewController = self;
}
- (void)postToTwitter {
NSLog(#"in postToTwitter %d", [SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]);
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
SLComposeViewController *tweetSheet = [SLComposeViewController
composeViewControllerForServiceType:SLServiceTypeTwitter];
// Sets the completion handler. Note that we don't know which thread the
// block will be called on, so we need to ensure that any required UI
// updates occur on the main queue
tweetSheet.completionHandler = ^(SLComposeViewControllerResult result) {
switch(result) {
// This means the user cancelled without sending the Tweet
case SLComposeViewControllerResultCancelled:
break;
// This means the user hit 'Send'
case SLComposeViewControllerResultDone:
break;
}
};
// Set the initial body of the Tweet
[tweetSheet setInitialText:#"just setting up my twttr"];
if (![tweetSheet addImage:[UIImage imageNamed:#"screen.png"]]) {
NSLog(#"Unable to add the image!");
}
if (![tweetSheet addURL:[NSURL URLWithString:#"http://twitter.com/"]]){
NSLog(#"Unable to add the URL!");
}
// Presents the Tweet Sheet to the user
[self presentViewController:tweetSheet animated:NO completion:^{
NSLog(#"Tweet sheet has been presented.");
}]; }
}
I am making casual game now.
I'd like to share the score with twitter.
My this work image is that below.
1.After game player plays the game and there is the score.
2.When the game goes to gameoverscene, they can push twitter button (using social.framework)
3. There is a text like "You got xx score !!" in the twitterdisplay(modal).
*I would like to change xx to the shared score.
Could you please give me some advices to do that ?
I am a beginner of Objective - C. So, easy way is better for me.
Little by little, I'd like to concern about security and scalability.
[Information]
*MainScene and GameOverScene are made from SKScene
MainScene.m
#implementation MainScene {
//The score
NSInteger _score;
}
- (void)incrementScore
{
_score++;
}
GameOverScene.m
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if([node.name isEqualToString:#"twitterbutton"]){
NSLog(#"self.delegate = %#",self.delegate);
[self.delegate showShareScreen];
//delegate to ViewController
if (nil == self.delegate) NSLog(#"delegate is nil");
}
}
ViewController.m
-(void)showShareScreen
{
NSLog(#"showShareScreen");
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
SLComposeViewController *tweetSheet = [SLComposeViewController
composeViewControllerForServiceType:SLServiceTypeTwitter];
tweetSheet.modalPresentationStyle = UIModalPresentationFormSheet;
tweetSheet.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[tweetSheet setInitialText:#"You got xx score"];
NSLog(#"self = %#",self);
[self presentViewController:tweetSheet animated:YES completion:nil];
}
else {
NSLog(#"not sls type twitter");
}
}
Change your line in delegate method in ViewController
[tweetSheet setInitialText:#"You got xx score"];
to as shown below; to include the score with a NSString's stringWithFormat: method
-(void)showShareScreenWithScore:(NSInteger) score {
NSLog(#"showShareScreen");
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
SLComposeViewController *tweetSheet = [SLComposeViewController
composeViewControllerForServiceType:SLServiceTypeTwitter];
tweetSheet.modalPresentationStyle = UIModalPresentationFormSheet;
tweetSheet.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[tweetSheet setInitialText:[NSString stringWithFormat:#"You got %d score",score]];
NSLog(#"self = %#",self);
[self presentViewController:tweetSheet animated:YES completion:nil];
}
else {
NSLog(#"not sls type twitter");
}
}
And from GameOverScene call this delegate method.
Note: When you are creating Game over scene at that time after object instantiation you can set the property of GameOverScene. So just declare a property
#property (assign , nonatomic) NSInteger score;
and set its value Using NSURLSession that the game is getting over. And score value you can get from MainScene score property.
NSURLSession
The NSURLSession class and related classes provide an API for
downloading content via HTTP. This API provides a rich set of delegate
methods for supporting authentication and gives your app the ability
to perform background downloads when your app is not running or, in
iOS, while your app is suspended.
I am using UIActivityViewController to present sharing options and I want to display another view controller when the UIActivityViewController is dismissed by the user or when the animation that follows "activityDidFinish:(bool)completed" gets over. When I try to present the other controller in the completion handler of the UIActivityViewController, I get the following warning and the second VC does not get displayed at all!
Attempt to present <_UIViewController: 0x1e16f020> on <###> while a presentation is in progress!
UIActivityViewController activityVC = [[UIActivityViewController alloc]initWithActivityItems:selectedAssetsURL applicationActivities:nil];
[activityVC setCompletionHandler:^(NSString *activityType, BOOL completed) {
NSLog(#"completed");
//Present another VC
}];
The question is, how to know when the UIActivityViewController disappears from the screen? Even the -ViewDidAppear method of the view controller which presents the UIActivityViewController does not get fired!
In this link there's good information about how the UIActivityViewController works:
http://www.apeth.com/iOSBook/ch26.html#_activity_view
Basically you can subclass the UIActivityViewController into another class and implement a method to know when it has been dissmissed.
UIActivityViewController* avc =
[[UIActivityViewController alloc]
initWithActivityItems:#[myCoolString]
applicationActivities:#[[MyCoolActivity new]]];
Here’s the preparatory part of the implementation of MyCoolActivity:
-(NSString *)activityType {
return #"com.neuburg.matt.coolActivity"; // make up your own unique string
}
-(NSString *)activityTitle {
return #"Be Cool";
}
-(UIImage *)activityImage {
return self.image; // prepared beforehand
}
-(BOOL)canPerformWithActivityItems:(NSArray *)activityItems {
for (id obj in activityItems) {
if ([obj isKindOfClass: [NSString class]])
return YES;
}
return NO;
}
-(void)prepareWithActivityItems:(NSArray *)activityItems {
self.items = activityItems;
}
To perform the activity, we implement one of two methods:
-(void)performActivity {
// ... do something with self.items here ...
[self activityDidFinish:YES];
}
-(UIViewController *)activityViewController {
MustacheViewController* mvc = [MustacheViewController new];
mvc.activity = self;
mvc.items = self.items;
return mvc;
}
And then MustacheViewController would have code like this:
- (IBAction)doCancel:(id)sender {
[self.activity activityDidFinish:NO];
}
- (IBAction)doDone:(id)sender {
[self.activity activityDidFinish:YES];
}