質問

I have a landscape based view that has a SKView (skView) inside of it. I want the width of skView to always be 100% of the view and a static height of 288. I have added some constraints but when I start the application in the simulator it ways gives me the same CGSize (568 x 288), regardless of if I pick iPhone 4 or 3.5.

- (void)viewDidLoad {
    CGSize size = self.skView.bounds.size; // 568 x 288
    ...
}

What am I missing here?

I've set up a sample project to illustrate the issue at hand https://github.com/kyledecot/autolayout

enter image description here

Update #1

One user suggested that I see what the value of self.skView.bounds.size is in viewWillAppear: which yielded some strange results (I'm not really sure if they're helpful)

enter image description here

Update #2

After removing all constraints and re-adding them as one commenter (updated in the github sample project I posted) suggested I now have the following (still broken though):

enter image description here

The lines in IB are blue which I means there is no ambiguity but it still doesn't seem to be working.

Update #3

After receiving new constraints from user matt and using viewWillAppear instead of viewDidLoad the problem still seems to be prevalent. It seems that skView's width never gets conformed to that of view

enter image description here

As you can see in the screenshot the text is cut off because on a 3.5 inch iPhone skView still has the width of 568 (iPhone 4 inch's width in landscape).

役に立ちましたか?

解決

It sounds like the constraints of the view haven't been resolved yet when your view configuration code kicks in. That is, the frames at that time do not correspond the "real" layout that you have created using auto layout constraints (which should fit the skView to the view).

I have moved the code from viewWillAppear to viewDidLayoutSubviews instead and it turns out that, at this time of the layout process, the bounds of your view and skView have been updated and it seems to work for both 3.5" and 4" screens.

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    CGSize skViewSize = self.skView.bounds.size;
    SKScene *scene = [MyScene sceneWithSize:skViewSize];
    scene.scaleMode = SKSceneScaleModeAspectFill;

    [self.skView presentScene:scene];
}

This tutorial might shed some more light on the topic.

Btw, I have submitted a pull request with my changes to your sample repository so you can browse the change.

他のヒント

viewWillAppear and viewDidLoad are called before the constraints are handled in view controller.
If your views rely on the size only when the view is created (e.g. presentScene in your code) then you are better do it in viewDidAppear or in 'viewDidLayoutSubviews'.
I have tried your code in each of these methods (after commenting out the viewWillAppear) and it works as expected.

EDIT
I have changed the scaleMode in wiewWillAppear from SKSceneScaleModeAspectFill to SKSceneScaleModeFill and it works good as well.
I think that this is better approach than presenting the scene only after the view controller is presented.

i think there is one short cut method.. first of all u have to checkmark on "Use Auto Layout" from the File Inspector, Then there is four button is showed in interface builder , 1:align 2:Pin 3:Reslove autolayout Issues and 4:resizing behaviour.. now select any object, you want to show same in landscape and portrait mode, and then click on third button(Reslove autolayout) .. select "add missing constrain in view controller" or "add missing constrain in view" as per your requirement.

There are two problems here.

First, your original constraints were completely wrong; you do not want a vertical space from the top and bottom of the SKView if you also want the vertical height to be fixed! Those two things are opposites of each other.

Second, there's a bug in Xcode. :( You can see it in your second set of constraints. The top constraint to the Top Layout Guide has come out wrong (you can see that from the -288). You have accidentally formed a constraint from the Top Layout Guide to the bottom of the SKView (that's the Xcode bug, it does that to you). Here's how to work around the bug:

  • Delete the top constraint.

  • Move the SKView down the screen.

  • Control-drag to form the top constraint to the Top Layout Guide again.

  • Now select the top constraint and manually set its Constant to 0, to make the SKView move back up again.

The result will be:

  • SKView has a height constraint of 280.

  • View (the main view) has a leading and following horizontal space constraint of 0 to the SKView, and a top constraint of 0 (not -288!) from the Top Layout Guide to the SKView.

Bingo, now everything will work correctly.

Actually i don't known the correct reason but put call layoutIfNeeded method and after it will show the currect size.

[self.skView layoutIfNeeded];
CGSize size = self.skView.bounds.size;

Inspired by @Michael Kessler's answer I've done some experiments.

In viewDidAppear I logged the sizes of the main view, skView and the scene. For different scaleModes here are the results.

SKSceneScaleModeAspectFill

viewSize = {480, 320}, skViewSize = {480, 280}, sceneSize = {568, 280}

SKSceneScaleModeFill

viewSize = {480, 320}, skViewSize = {480, 280}, sceneSize = {568, 280}

SKSceneScaleModeResizeFill

viewSize = {480, 320}, skViewSize = {480, 280}, sceneSize = {480, 280}

So clearly the mode you want is SKSceneScaleModeResizeFill to make the scene size match exactly the view size.

You will note however that Hello, World is still off the right side of the screen. The reason is that the position of the SKLabel is set when the SKScene is initialised which is in viewDidAppear when the scene size is the incorrect width.

You can reposition it as follows in your MyScene class. When the SKScene is resized this method is called.

-(void)didChangeSize:(CGSize)oldSize {
    _myLabel.position = CGPointMake(self.size.width, self.size.height/2.0);
}

NOTE: Things appear to work with SKSceneScaleModeFill but what you have there is a scene of width 568, scaled to fit in 480 rather than a scene of width 480.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top