1

I have created a simple iPhone application that has a tutorial (a series of 5 images) when the user downloads the app for the very first time where they can click Next and cycle through the images. Currently there's no way to play the tutorial again but in my update, I'd like to introduce this feature, some like apps have within their settings of the app itself.

I have a Tab Bar with three table view controllers Timeline, Event and Settings. When the user goes to the Settings tab and selects the "Play Tutorial Again" Table View Cell, I want that to start the tutorial again.

In my Timeline View (the root view), I have the following code:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];        
    if ([TutorialViewController hasSeenTutorial] == NO) {
    NSArray *tutorialImages = @[[UIImage imageNamed:@"Tutorial 1.png"],
                                        [UIImage imageNamed:@"Tutorial 2.png"],
                                        [UIImage imageNamed:@"Tutorial 3.png"],
                                        [UIImage imageNamed:@"Tutorial 4.png"],
                                        [UIImage imageNamed:@"Tutorial 5.png"]];
    TutorialViewController *tutorial = [[TutorialViewController alloc] initWithImages:tutorialImages];
    [self presentViewController:tutorial animated:YES completion:nil];
    [TutorialViewController setHasSeenTutorial:YES];
        }
}

- (void)displayTutorial
{

    NSArray *tutorialImages = @[[UIImage imageNamed:@"Tutorial 1.png"],
                                [UIImage imageNamed:@"Tutorial 2.png"],
                                [UIImage imageNamed:@"Tutorial 3.png"],
                                [UIImage imageNamed:@"Tutorial 4.png"],
                                [UIImage imageNamed:@"Tutorial 5.png"]];

    TutorialViewController *tutorial = [[TutorialViewController alloc] initWithImages:tutorialImages];
    [self presentViewController:tutorial animated:YES completion:nil];
}

The TutorialViewController's code is:

static NSString * const kHasSeenTutorial = @"hasSeenTutorial";

+ (BOOL)hasSeenTutorial
{
    return [[NSUserDefaults standardUserDefaults] boolForKey:kHasSeenTutorial];
}

+ (void)setHasSeenTutorial:(BOOL)hasSeenTutorial
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setBool:hasSeenTutorial forKey:kHasSeenTutorial];
    [defaults synchronize];
}

- (id)initWithImages:(NSArray *)imageArray
{
    self = [super init];
    if (self) {
        if (imageArray == nil) {
            [[NSException exceptionWithName:NSInvalidArgumentException reason:@"imageArray cannot be nil." userInfo:nil] raise];
        }
        self.images = imageArray;
    }
    return self;
}

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

- (void)viewDidLoad
{

    [super viewDidLoad];

    UIImageView *imageView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [self.view addSubview:imageView];
    self.imageView = imageView;

    CGRect buttonFrame = [[UIScreen mainScreen] bounds];

        buttonFrame.origin.y = 519.0;
        buttonFrame.origin.x = 250.0;
        buttonFrame.size.height = 51.0;
        buttonFrame.size.width = 70.0;

        UIButton *nextButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];

        [nextButton setTitle:@"Next" forState:UIControlStateNormal];
        [nextButton addTarget:self action:@selector(nextButtonWasTapped:) forControlEvents:UIControlEventTouchUpInside];

        nextButton.frame = buttonFrame;
        nextButton.backgroundColor = [UIColor whiteColor];

        nextButton.showsTouchWhenHighlighted = YES;
        nextButton.adjustsImageWhenHighlighted = NO;
        nextButton.tintColor = [UIColor purpleColor];
        nextButton.titleLabel.font = [UIFont systemFontOfSize:18.0];
        nextButton.opaque = NO;

        [self.view addSubview:nextButton];
        self.nextButton = nextButton;

        // ----------------------------------------------------------------------

        currentIndex = 0;

        if (self.images == nil) {
            self.images = @[];
        }


}

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

- (void)setImages:(NSArray *)images
{
    _images = images;
    [self resetToStart];
}

- (void)resetToStart
{
    [self.nextButton setTitle:@"Next" forState:UIControlStateNormal];
    currentIndex = 0;
    if (currentIndex < self.images.count) {
        self.imageView.image = self.images[currentIndex];
    }

    [self.view bringSubviewToFront:self.nextButton];
}

- (void)nextButtonWasTapped:(id)sender
{
    currentIndex++;
    if (currentIndex < self.images.count) {
        self.imageView.image = self.images[currentIndex];

        if (currentIndex == self.images.count - 1) {
            [self.nextButton setTitle:@"Start" forState:UIControlStateNormal];
        }
    }

    if (currentIndex == self.images.count) {
        [self dismissViewControllerAnimated:YES completion:nil];
        [EnvylopeTutorialViewController setHasSeenTutorial:YES];
    }
}

From the looks of it, I'm guessing I would just do something like call ResetToStart, or something similar, but I'm really not sure how I would do this. The Images are communicated in the Timeline but I'm playing the tutorial from the Settings, so I'm guessing I would have to set up some similar methods in the Settings Table View, etc. I'm really lost on this one

So from the Settings Tab, I'd like to be able to play the tutorial all over again with the same images, buttons, etc by clicking on the "Play Tutorial" Table View Cell.

In the App Settings View Controller, I have:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if ([cell.textLabel.text isEqualToString:@"Play Tutorial Again"])
    {
        NSLog(@"The Tutorial is going to play"); 
        [self displayTutorial]; 
    }


}

But the displayTutorial method isn't being called.

Any guidance on this would be really appreciated.

amitsbajaj
  • 1,304
  • 1
  • 24
  • 59
  • Just invoke your Tutorial code with `didSelectRow` in your settings view omitting the `hasSeenTutorial` elements – JSA986 Mar 25 '14 at 11:16
  • Thanks @JSA986 - I have put the -(void)displayTutorial code in the App Settings to be called from the DidSelectRow, but it never seems to get called. I don't have a storyboard view controller for the tutorial again or anything and no "segue" from the Play Tutorial Again cell.. am I missing something? – amitsbajaj Mar 25 '14 at 11:52
  • You say you have no storyboardViewController for the tutorial but in your code there is `TutorialViewController`? you should be placing `TutorialViewController *tutorial = [[TutorialViewController alloc] initWithImages:tutorialImages]; [self presentViewController:tutorial animated:YES completion:nil];` in your `didSelectRow` in settings to present the tutorial – JSA986 Mar 25 '14 at 11:59
  • Ahh yes, my mistake but that works like a charm. Thanks so much for that. Do you mind posting an answer to this question so I can accept it? Thanks so much again - that works really well – amitsbajaj Mar 25 '14 at 13:43
  • Glad it helped and ive posted it as an answer – JSA986 Mar 25 '14 at 13:56

1 Answers1

1

Just invoke your Tutorial code with didSelectRow in your settings view, omitting the hasSeenTutorial code

Place TutorialViewController *tutorial = [[TutorialViewController alloc] initWithImages:tutorialImages]; in your didSelectRow method in your settingsViewController to present the tutorial at any time

JSA986
  • 5,870
  • 9
  • 45
  • 91