0
- (IBAction)StartGame:(id)sender
{
    MainGameDisplay *secondPage = [[MainGameDisplay alloc] initWithNibName:nil bundle:nil];

    [self.view addSubview:secondPage.view];
    secondPage.view.frame = CGRectMake(568, 0, 568, 320);//(N = horizontal, N = vertical)
    [UIView animateWithDuration:1.0f
                     animations:^{
                         //actual frame needed with an animation.
                         secondPage.view.frame = CGRectMake(0, 0, 568, 320);
                     }
                     completion:^(BOOL finished) {
                         //ENTER HERE ANYTHING TO RUN AFTER ANIMATION IS COMPLETED:
                         [self presentViewController: secondPage animated:NO completion:NULL];
                         //This will make the next page load correctly after the transition, otherwise you cannot. interact with anything.
                     }];
}

This works perfectly for entering the view. Without [self presentViewController: secondPage animated:NO completion:NULL];, you cannot interact with the new page, any button you click causes it to crash.

If I return back to the first page, doing it normally, it's fine, but if I click StartGame again, the program changes views and then simply crashes. The problem is with the line [self.view addSubview:secondPage.view];, if I comment this out, the program doesn't crash but when it changes views it doesn't transition and instantly appears.

The transition is also pretty laggy/glitchy in landscape mode, perfect in portrait though.

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
PappaSmalls
  • 349
  • 2
  • 13
  • What are the defining characteristics of `secondPage.view`? Is secondPage a view controller? How is secondPage.view initialized. Reading between the lines, I'm guessing that `MainGameDisplay` is a view controller, and that you're not explicitly defining secondPage.view. If that's the case, secondPage.view will _not_ be initialized until MainGameDisplay's `viewDidLoad` method has been called, and that in turn will not be called until secondPage is actually added to the displayed view controller hierarchy, which `presentViewController` would accomplish. My guess is that view is `nil`. – KevinH Nov 11 '12 at 16:57
  • MainGameDisplay is the ViewController, secondPage is being initialised and allocated on the first line, and secondPage.view is just an instance of MainGameDisplay.view. Do you know what the problem might be then? – PappaSmalls Nov 11 '12 at 18:20

3 Answers3

1

Here you are Adding secondPage on currentView as aSubview. and Again your presenting it. I think it causing some memory related thing may be some other thing(it would be much clear if you put some crash log here in your question). But i'll suggest you no need to present secondPage Again .Here is your Code i made Single Line Change here .

   - (IBAction)StartGame:(id)sender
      {
      MainGameDisplay *secondPage = [[MainGameDisplay alloc] initWithNibName:nil bundle:nil];



    [self.view addSubview:secondPage.view];
    secondPage.view.frame = CGRectMake(568, 0, 568, 320);//(N = horizontal, N = vertical)
    [UIView animateWithDuration:1.0f
                 animations:^{
                     //actual frame needed with an animation.
                     secondPage.view.frame = CGRectMake(0, 0, 568, 320);
                 }
                 completion:^(BOOL finished) {

                     //ENTER HERE ANYTHING TO RUN AFTER ANIMATION IS COMPLETED:

You should comment below sinlge because you have already added secondPage as a Subview on currentView.so further no need to present it again.

                   //  [self presentViewController: secondPage animated:NO completion:NULL];
                     //This will make the next page load correctly after the transition, otherwise you cannot. interact with anything.
                 }];

}

Edit: For Landscape Mode you should change coordinate while you are setting the frame secondPage view . i think here you are creating this view for 4 inch Devices. here you can do this by setting some checks as this

   if(checkIfDeviceIsInlandscae)
    {
       secondPage.view.frame = CGRectMake(568, 0, 568, 320);

    } 

   else 
    {
      secondPage.view.frame = CGRectMake(320, 0, 320, 568);
    }

Inside the animation block change the frame according to the orientation, as i did above tow line.

Kamar Shad
  • 6,089
  • 1
  • 29
  • 56
  • Like I said, if I comment out that line, I cannot interact with anything on the new page, if I click on anything the program crashes. If I have the line, everything is okay. I also dont get anything in the crash log, this just appears highlighted in Xcode: "0xf660b: calll 0xf6610 ; -[UIViewController loadViewIfRequired] + 17" – PappaSmalls Nov 08 '12 at 19:34
  • @SinaYamani off course not any problem then in that case you should only allow landscape orientation. here is the link you can mange it as http://stackoverflow.com/questions/13023936/orientation-issue-in-ios-6/13024015#13024015 – Kamar Shad Nov 08 '12 at 19:53
0

One problem is by calling both presentViewController: and addSubview: you are adding the view twice. I suspect you find it necessary to call presentViewController: because it invokes viewDidAppear: and you're using that to hook up the UI in secondPage. I'd put a logging statement in MainGameDisplay's viewDidAppear: method and see when it is getting called.

One fix may be to just replace [self presentViewController: secondPage animated:NO completion:NULL] with [secondPage viewDidAppear:NO].

Josh Knapp
  • 154
  • 2
  • 5
0

Your problem is one of memory allocation/deallocation. You're not retaining secondPage anywhere, and as such it will be deallocated after the StartGame method logic is completed. This deallocation will in turn deallocate MainGameDisplay's ivars/properties too, including MainGameDisplay.view. This will all happen before you start to interact with the displayed view, so the moment you try to change values or interact with the no-longer-existent view, you're going to crash with an EXC_BAD_ACCESS error.

If you truly want to manage MainGameDisplay.view outside of the view controller, you'll need to retain secondPage in an ivar or member variable in your parent class:

ParentClass.m:

@interface ParentClass ()
{
    MainGameDisplay *_secondPage;
}

@end

...

- (IBAction)StartGame:(id)sender
{
    _secondPage = [[MainGameDisplay alloc] initWithNibName:nil bundle:nil];
    [self.view addSubview:_secondPage.view];

    ...

}

However, this is not generally a recommended design pattern. It's the responsibility of a view controller to manage its view, particularly layout changes that might be made, animations in how it's displayed, etc. You're violating the encapsulation responsibilities of MainGameDisplay. You should consider doing whatever view management you need to do inside of MainGameDisplay.

I would recommend reading through the View Controller Programming Guide for iOS. It will explain the fundamentals around what you're trying to do, and best practices for doing it.

KevinH
  • 2,034
  • 1
  • 12
  • 12
  • You have declared StartGame in the ParentClass, how would that work when the button is on SuperClass's subview? – PappaSmalls Nov 11 '12 at 20:36
  • I don't know what you're referring to when you say "the button" or "SuperClass". – KevinH Nov 11 '12 at 20:52
  • Meant to put "ParentClass", the button is StartGame which would be in "ParentClass's" subclass as you have said, but how would the subclass see or use the IBAction? The debug also gives me "EXC_BAD_ACCESS (code=2" – PappaSmalls Nov 11 '12 at 21:02
  • What I would suggest would be to move the call to `[UIView animateWithDuration:animations:completion:]` to the `viewDidLoad` method of `MainGameDisplay`. Then, rather than create an ivar to store your instance of MainGameDisplay, simply allocate it and add it to the UI hierarchy by using `[self presentViewController:animated:completion:]`. (presentViewController will retain a reference to MainGameDisplay in that case). That way, the UIViewController is managing its own view, and you don't run into the memory management issues that arise from taking that responsibility away. – KevinH Nov 11 '12 at 21:56
  • Okay, I added this to viewDidLoad of MainGameDisplay: if (!self.mainPage) self.mainPage = [[MainGameDisplay alloc] initWithNibName:nil bundle:nil]; [self presentViewController: self.mainPage.view animated:NO completion:NULL]; and in .h I have : @property (strong) MainGameDisplay *mainPage; but I get "Incompatible pointer types sending 'UIView *' to paramenter of type 'UIViewController *'" – PappaSmalls Nov 11 '12 at 22:34
  • I don't think we're on the same page. Given that, and the relatively small amount of code being submitted to explain your situation, I'll just defer to again recommending the [View Controller Programming Guide for iOS](http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40007457). I think it will help you better understand how to separate views and their controllers in your app, and how to make them work together. Good luck! – KevinH Nov 12 '12 at 02:36