cannot modify frame of UIImageView if added throug

2019-07-13 11:43发布

问题:

I came across this very peculiar problem where I am unable to modify the frame of a UIImageView.

I have isolated it to this very simple example. Starting from a default single view application xcode template, I add a UIImageView in Interface Builder, link it to the ViewController property called testImage, and in ViewController.m I add:

-(void)viewDidAppear:(BOOL)animated{
    UIImageView* maskImage = [[UIImageView alloc] initWithFrame:self.testImage.frame];
    maskImage.image = self.testImage.image;
    maskImage.alpha = 0;
    [self.view addSubview:maskImage];
    self.testImage.frame = CGRectMake(10, 10, 10, 10);
}

and it does not work. The test image remains resolutely where it was. If I do not add maskImage to view, the example works. And, yes I am sure I am not covering the destination with maskImage.

If I do not use the IB to place the image, but instead use:

self.testImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 100, 300, 300)];
self.testImage.image = [UIImage imageNamed:@"jim-105.png"];
[self.view addSubview:self.testImage];

in viewDidLoad it all works as expected.

I have also tried to just place the image in IB, then set its properties in viewDidLoad, but with the same effect. I have been trying this in Xcode5. I do not have access to previous Xcode here, and I am not sure is this an expected behaviour (and if so why) or is this a bug?

回答1:

I'd expect precisely the behavior you describe if you were using auto layout, in which attempts to adjust the frame can be thwarted when constraints are reapplied (which can happen with the most incidental of events, such as adding another view to the main view) and the frame will be recalculated. If you have an autolayout view with constraints, to change its size you change its constraints.

If you're wondering why the programmatically created testImage works as expected, it's because by default, the programmatically created view has translatesAutoresizingMaskIntoConstraints turned on. Thus, attempts to change the frame persist.

If you're using autolayout and want to change the frame, you can accomplish this by adding IBOutlet references for the constraints in Interface Builder. Let's say you had top, leading, width and height constraints for your view. You could then change it's frame (in this example, to CGRect(0, 100, 300, 200)) with:

self.imageViewLeadingConstraint.constant = 0;
self.imageViewTopConstraint.constant = 300.0;
self.imageViewWidthConstraint.constant = 300;
self.imageViewHeightConstraint.constant = 200;

Clearly, you need those four IBOutlet references, but once you do that, it's quite easy.