NSImageView setImage won't set image - objective-c

I am trying to set image for an NSImageView instance object in a Cocoa project. My code looks like this:
itemTableCellView * xx = [tableView makeViewWithIdentifier:#"MainCell" owner:self];
xx.label.stringValue = [tempCi simpleTxt];
xx.img = [[NSImageView alloc]initWithFrame:CGRectMake(48, 48, 48, 48)]];
NSImage * localimage = [NSImage imageNamed:#"menubar icon"];
[xx.img setImage:localImage];
return xx;
The variable imgis of type NSImageView. The variable localImage loads the correct image, I have checked it in the log. The variable lable is initialized correctly and gets the right value
I just keep on getting empty NSImageViews in my app.

Your NSImageView is initialized with no size (it's frame equals NSZeroRect), also you don't add the image view to any subview.

when you create your NSimageView,try doing an initwithframe:. This will set a size for the NSImageView. I believe that you might be drawing in a rect of size zero otherwise.

You should use
xx.img = [[NSImageView alloc] initWithFrame:CGRectMake(x, y, width, height)];
Or, maybe, as img is property, you don't need to init it at all?
And just use
xx.img.frame=CGRectMake(x, y, width, height);

Well, yet another quirk of Objective-C!
I found out that even when a NSImageView is a property of an NSView, it needs to be added to it through:
[xx addSubview:xx.img];
Well, played Cocoa, very well played!
cheers!

Related

UIImageView autoresizingmask not working in certain cases

I am experimenting with a block-breaking iOS app to learn more about UI features. Currently, I am having issues trying to make it work for screen rotation.
I am able to get the blocks to re-arrange properly after screen rotation but am having trouble with getting the UIImageView for the paddle re-arrange.
My code is split as follows, VC calls initializes an object of the BlockModel class. This object stores a CGRect property (which is the CGRect corresponding to the paddle's ImageView).
The VC then creates an imageView initialized with the paddle image, sets the autoresinging property on the image view (to have flexible external masks), sets the frame based on the CGRect in the model object and adds the imageView as a sub-view of the main view being handled by the VC.
The code is below.
When I rotate, I am seeing that the ImageView is not being automatically repositioned.
If I do all the image view and CGRect creation in the vC, then it works (code sample 2).
Is this expected behavior? If yes, why is autoresizing not kicking in if the CGRect is obtained from a property in another object?
Full Xcode project code is here (github link)
EDIT
Looks like things don't work if I store the imageView as a property. I was doing this to have quick access to it. Why doesn't it work if imageView is stored as a property?
Code where model is initialized
self.myModel = [[BlockerModel alloc] initWithScreenWidth:self.view.bounds.size.width andHeight:self.view.bounds.size.height];
Model initialization code
-(instancetype) initWithScreenWidth:(CGFloat)width andHeight:(CGFloat)height
{
self = [super init];
if (self)
{
self.screenWidth = width;
self.screenHeight = height;
UIImage* paddleImage = [UIImage imageNamed:#"paddle.png"];
CGSize paddleSize = [paddleImage size];
self.paddleRect = CGRectMake((self.screenWidth-paddleSize.width)/2, (1 - PADDLE_BOTTOM_OFFSET)*self.screenHeight, paddleSize.width, paddleSize.height);
}
return self;
}
Code in VC where imageView is initialized
self.paddleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"paddle"]];
self.paddleView.backgroundColor = [UIColor clearColor];
self.paddleView.opaque = NO;
self.paddleView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin;
NSLog(#"Paddle rect is %#",NSStringFromCGRect(self.myModel.paddleRect));
[self.paddleView setFrame:self.myModel.paddleRect];
[self.view addSubview:self.paddleView];
If I instead use this code in the VC to initialize imageView things work
UIImage* paddleImage = [UIImage imageNamed:#"paddle.png"];
CGSize paddleSize = [paddleImage size];
CGRect paddleRect = CGRectMake((self.view.bounds.size.width-paddleSize.width)/2, (1 - PADDLE_BOTTOM_OFFSET)*self.view.bounds.size.height, paddleSize.width, paddleSize.height);
UIImageView *paddleView = [[UIImageView alloc] initWithImage:paddleImage];
paddleView.backgroundColor = [UIColor clearColor];
paddleView.opaque = NO;
paddleView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin;
[paddleView setFrame:paddleRect];
[self.view addSubview:paddleView];
Found the issue. I was using the model object to handle all my "game object location" logic. E.g VC would calculate the X axis deltas from the touch events & forward them to the model object. Also, CADisplayLink events would be forwarded so that model can update ball location based on velocity and time since last event. It will then use updated location to detect collisions. This split was used because model class also had the methods to detect collisions with sides, paddle/ball etc.
The issue was that the model object was rewriting the CGRect of the paddleView by adding the delta it received from VC to the origin.x of current paddleRect it had stored. This paddleRect did not take into account the automatic adjustment to the CGRect that is done by auto-resizing after a rotation.
The fix was for the VC to set the CGRect of the paddleRect (set to paddleView frame) before calling the method in the model to update all the game properties and detect collisions. This way model only takes care of logic of collusion detection and updating ball movement and velocity based on it. The VC uses current paddleView location and hence automatically accounts for the automatic adjustment to the CGRect that is done by auto-resizing after a rotation.
Source code in github link updated.

Cannot set button frame correctly over imageview in objective c

I'm setting a button over an imageview, but can't get the frame right. I don't understand why. Here's an image of the problem: https://docs.google.com/document/d/1ZrZs_eLfZaOov1cf6Hi0NA37MHLQmyf_j39g172lXXc/edit?usp=sharing
I tried using tap gestures; that didn't work. I tried setting the frame by referencing the bounds and frame of the imageview, and that didn't work either
May be you should read more about differences between frame and bound properties of UIView.
In your code you should use:
clearButton.frame = [self.imageView convertRect:self.imageView.bounds toView:self.view];
[self.view addSubview:clearButton];
or
clearButton.frame = self.imageView.bounds;
[self.imageView addSubview:clearButton];
self.imageView.userInteractionEnabled = YES;
to set clearButton's frame and add it to a parent view.

Creating a dropshadow for UITableView

Would somebody please explain how to create a one or two pixel drop shadow ONLY on the the very last cell (in other words, I don't want a shadow around the entire tableview, just the bottom cell. An image of what I'm talking about:
Solved. Use the following code to produce a very nice, subtle shadow to the bottom of your UITableViewCell. Makes it look like it's raised slightly out of the page :)
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(3, 49, cell.frame.size.width-26, 3)];/// change size as you need.
separatorLineView.backgroundColor = shadowColor;// you can also put image here
UIBezierPath *roundedShadow = [UIBezierPath bezierPathWithRoundedRect:separatorLineView.bounds byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight cornerRadii:CGSizeMake(8.0f, 8.0f)];
CAShapeLayer *newSeparatorShape = [[CAShapeLayer alloc] init];
[newSeparatorShape setPath:roundedShadow.CGPath];
separatorLineView.layer.mask = newSeparatorShape;
[cell.contentView addSubview:separatorLineView];
Also, don't forget to put this at the top of your .m file #import <QuartzCore/QuartzCore.h>
You could, in tableView:cellForIndexPath: set the cell's background image to one that includes the rounded corners with the shadow.

Passing UIImage to a function and Edit it externally

Let's say we have this part of code for a UIView subclass:
self.myImage = [UIImage imageNamed:#"img1.jpg"];
[self myFunc:self.myImage];
myFunc is here defined:
-(void)myFunc(UIImage*)img{
UIImageView *imgView = [[UIImageView alloc]initWithImage:img];
[self addSubview:imgView];
}
Now i show in my view img1.jpg, if i decide to change self.myImage AFTER myFunc call
self.myImage = [UIImage imageNamed:#"img2.jpg"];
why i continue to show img1 and not img2 ??? myFunc receive a UIImage pointer not directly an object... i'm pretty confused and i missed something really important i think.
Edit --
I'd like to have many UIImageView, and every image ivar of these view must pointing to the same image address, changing image at this address every UIImageView have a new image how can i do that ?
Given your code. Let say that when you load img1.jpg into memory it went to address 1000. And you use the ivar myImage to point to it. When you pass that ivar to your function and create the UIImageView it also points to img1.jpg.
Now, when you load img2.jpg into memory it went to a different address, for example 2000. And then updated the ivar myImage to point to that new location. img1.jpg is still in address 1000 and is still being used by the UIImageView.
If you want to change the image of the UIImageView you will have to use the image property of that class.
The UIImage that you've given to the UIImageView does in fact not know itself the view it belongs to. It may be used in different views. You have to ask the UIImageView object for the current image that it displays. If you want to change the displayed image you would write:
self.imgView.image = [UIImage imageNamed:#"img2.jpg"];
Better you add a property for the UIImageView so that you can access it from everywhere in the class.

Does anyone know how I can get the "real" size of the UIImageView instead of creating a frame

I was hoping there was some sort of function that could take the real size of my picture
CGRect myImageRect = CGRectMake(0.0f, 0.0f, 320.0, 210.0f); // 234
UIImageView *myImage = [[UIImageView alloc] initWithFrame:myImageRect];
[myImage setImage:[UIImage imageNamed:#"start.png"]];
And with CGRectMake which does something like this ..( imageViewHeight ,
CGFloat imageViewHeight = [myImage frame].size.height;
So that I could get the real size instead of having to define it like you can seen above.
I don't really get what you're asking, but here's a shot:
If you have a UIImage, and you want to know its size, you can ask it for its -[UIImage size] property.
However, if you want to create a UIImageView that's the same size as a UIImage, then you can just use -[UIImageView initWithImage:], which will automatically set the frame of the UIImageView to correspond to the dimensions of the image.
If, however, you're just looking to change the dimensions of a currently existing view, there's really no easy way to do that without messing around with the view's frame. You could maybe apply an affine transform to scale it, but it's easier to manipulate the frame.
It looks like you're asking to add the image to the imageview without first creating a frame. If this is the case, you can do the following:
UIImageView *myImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"start.png"]];
As far as I understood, you are looking for the size of the image used in UIImageView object. To do that, there is not a function built in UIImageView but you can do it this way:
NSString* image= [myImage image].accessibilityIdentifier; // Get the image's name
UIImage *img = [UIImage imageNamed:image]; // Create an image object with that name
CGSize size = img.size; // Get the size of image
Hope this helps your question.