Button's image as a conditional? - objective-c

I'm trying to create a conditional that asks about the button's image.
Here's what I have:
if (buttonName.image == [UIImage imageNamed:#"ButtonImage.png"])
This code works fine if the object buttonName is a UIImageView, but as a UIButton, I get the error 'request for member 'image' in something not a structure or union'.
How can I create this conditional?

== checks for pointer equality, so generally I would recommend using isEqual: which works on NSObjects, but this may not work for a UIImage (though UIImage does inherit from NSObject so give it a go).
If that fails, you might try using the CGImage property of a UIImage. This is the underlying Quartz image data, so you may be able to detect if the two images have the same CGImage (again, using == will not work, but isEqual may).
One way around this is to use the tag property of the UIButton, but this takes only ints, so you'll have to do some re-writing.

Related

What type of parameters should be in a custom initializer?

When adding a custom initializer to a subclass, are there any rules as to what kind of parameters it should take? As an example, is there a particular reason why UIView doesn't have the initializer below, and would there be any argument for not adding it to a custom subclass of UIView?
- (instancetype)initWithFrame:(CGRect)frame backgroundColor:(UIColor *)backgroundColor;
I haven't been able to find an answer to this on the web, so I hope that some of you can enlighten me.
You can add anything in there. But then you can add so many that it becomes ridiculous...
initWithFrame:backgroundColor:tintColor:alpha:hidden:userTouchEnabled:...
It really depends on what you're using the subclass for.
For instance, you might create a PlayingCardView subclass. This is going to have certain properties... suit, faceValue. Because every card MUST have a suit and face value it makes sense to put these into the init method.
So it would be sensible to create an initialiser...
- (instancetype)initWithSuit:(Suit *)suit faceValue:(FaceValue *)faceValue;
because every card has to have a suit and a face value.
Equally, you could have another property backImage to set the image on the "back" of the card. So you could have...
- (instancetype)initWithSuit:(Suit *)suit faceValue:(FaceValue *)faceValue backImage:(UIImage *)backImage;
Now you can use one of two initialisers. One for the "default" back image the other to set a custom back image.
Then you get into designated initialisers in this case, it would be preferable not to have repeated code in both init methods so you would make the first method like this...
- (instancetype)initWithSuit:(Suit *)suit faceValue:(FaceValue *)faceValue
{
UIImage *defaultBackImage = [UIImage imageNamed:#"defaultCardImage"];
return [self initWithSuit:suit faceValue:faceValue backImage:defaultBackImage];
}
And the designated initialiser would do all the actual setting up of the card.
In reality though, there is no fixed way and no correct way of doing this and it can take a while to find a pattern that you find easiest/best to use.
Your custom initializer can take any parameter you want to. As any other class, UIView define some let's say basic behaviour, so if you need any other behaviour you are free to add it using a subclass for example. Don't complain that UIView or any other classes don't have methods that you think would be good for them to have.
I would recomend you not write a custom initializer which has many arguments because it increase the complexity. Think exactly what is needed for that classes to be initalized correctly.

How can I change the value of an NSImage?

I am a beginning Objective-C programming programmer, and I want to change the value of an NSImage. That means that if I have an NSImage that is a NSStatusUnavaliable, how could I make it a NSStatusAvaliable? Thanks!
So I believe what you're asking is: Somewhere you have an NSImage instance that was initialized like:
NSImage *image = [NSImage imageNamed: #"NSStatusUnavailable"];
And you would like to use the image that is mapped to #"NSStatusAvailable".
Without going into details, you really want to assign your image to [NSImage imageNamed: #"NSStatusAvailable"];
Take a look at the docs for NSImage. Specifically what you might find useful is the imageNamed: class method.
Discussion
This method searches for named images in several places, returning the first image it finds matching the given name. The order of the search is as follows:
Search for an object whose name was set explicitly using the setName: method and currently >resides in the image cache.
Search the app's main bundle for a file whose name matches the specified string. (For information on how the bundle is searched, see ““Accessing a Bundle's Contents”“ in >Bundle Programming Guide.)
Search the Application Kit framework for a shared image with the specified name.
But also since you're new, just reviewing Objective-C docs on object life cycle will be very useful to understand what's going on.
Swift:
let 🈯️ = NSImage(named: .statusAvailable)
let 🅿️ = NSImage(named: .statusPartiallyAvailable)
let 🔴 = NSImage(named: .statusUnavailable)
let 🔶 = NSImage(named: .statusNone)

iOS: Change contents of self (UIImage)

I have written some code in a UIImage category that takes a UIImage (self) and then redraws it using CGContextRef. Is there any way to rewrite the UIImage (self) while using CGBitmapContext? Currently, I have it returning the image that was created through the CGContextRef, but is it possible to rewrite the image itself within that method?
From the UIImage documentation:
Image objects are immutable, so you cannot change their properties
after creation. ... Because image objects are immutable, they also do
not provide direct access to their underlying image data.
It is therefore not possible to change the image data of an UIImage after is has been created.

Where can I use drawInRect for strings?

I'm having some trouble tracking down the exact usage of drawInRect; I know the syntax, but is it only available inside a UIView or its subclass? What exactly is the "context" required, and how to I create or get it?
The context is like the canvas for core graphics drawing. You can get the context from any UIView by calling UIGraphicsGetCurrentContext() within drawRect:. You can also create your own context anywhere, from which you can create a UIImage or save to a file, etc.
Hope this helps!

NSImage size problem

I'm using the same image resource in two different controllers. In both controllers the image is shown in different sizes, the problem is that once the image is shown in a smaller size than the original, the next time I get the image by [NSImage imageNamed:#"resource.png"] the image size is set to the last size it took. I tried by invoking the recache method on NSImage and also tried to set the cache mode to any the posible value, but it didn't work.
Any ideas?
You should never modify an instance of NSImage obtained from imageNamed:. The returned instance is shared with other clients, so it should not be changed.
If you have to setSize: on the image, just make a copy and use that one:
NSImage *image = [[[NSImage imageNamed:#"foo.png"] copy] autorelease];
[image setSize:(NSSize){128, 128}];
The thing is that
[NSImage imageNamed]
As you mentioned is in the cache, and as long as it is in the cache it will return the cached image so what you need to do is first released the previous reference or use the object's setName method and setting to nil. Here is the documentation reference:
The NSImage class may cache a reference to the returned image object for performance in some cases. However, the class holds onto cached objects only while the object exists. If the image object is subsequently released, either because its retain count was 0 or it was not referenced anywhere in a garbage-collected application, the object may be quietly removed from the cache. Thus, if you plan to hold onto a returned image object, you must retain it like you would any Cocoa object. You can clear an image object from the cache explicitly by calling the object’s setName: method and passing nil for the image name.