I have created a UIImage subclass named MyImage.
MyImage obviously responds to every method originally implemented by UIImage. I would like to completely hide UIImage implementation, so for example MyImage redeclares a method like:
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets;
to
- (MyImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets;
I attempt to write the implementation like:
- (MyImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets {
UIImage *original = [super resizableImageWithCapInsets:capInsets];
MyImage *result = [[[self class] alloc] initWithUIImage:original];
return result;
}
- (id) initWithUIImage:(UIImage *)image {
// HOW TO IMPLEMENT THIS METHOD???
}
but I stopped at initWithUIImage method. How can I achieve such a behavior without using composition?
You don't want to do that. Its a lot of unnecessary code with a high risk of breaking something. Don't redeclare these methods. Is there a specific reason that you want to do that?
The problem here is simple and it is called: INHARITANCE.
Do not do inaritance but provide some class which owns UIImage. It will be easier and more relialeble.
Another issue is that you didn't expain why you need change something in UIImage! I'm prety sure yuo are trying to resolve some simple problem in nasty way.
The answer is that you cannot do what it seems like you're attempting to do. MyImage IS a UIImage, meaning it implicitly has all methods and properties of UIImage. You can add new ones, but never remove existing ones.
And UIImage is used all over the system APIs. What exactly are you attempting to accomplish by doing this?
Related
I have created on custom imageView class. And am trying to override the image setter method. But for some reason the imageView is not displaying anything, though the image is getting assigned onto it.
The code is as follows:
#implementation CustomImageView
#synthesize image = _image;
- (void)setImage:(UIImage *)correctedImage
{
_image = correctedImage;
}
#end
I have tried removing the setter method. i.e Without overriding any method at all. Still it is not displaying anything. :(
The problem was that I had to set the image by passing it to the super.
[super setImage: correctedImage];
Simply, setting it from the base class doesn't seen to work :/
This is probably a ridiculous question but I just can't figure it out for the life of me. I have a class which subclasses NSObject which has a property called image setup, like this:
#property (strong, nonatomic) UIImage *image;
Somewhere else I initialize the class and attempt to set the image in the class, like this:
UIImage *image = [UIImage imageNamed:#"Test"];
Class *item = [[Class alloc] init];
item.image = image;
But when I try to call item.image it is always nil.
The image called Test is in the project and is used elsewhere so I know it has access to the image, but for some reason it isn't being copied to the instance of my class. I have put NSLog messages and breakpoints directly after setting the image which have shown it to be nil as well as using commands via the debugger which have also shown the image in the class to be nil while the UIImage I create to copy is not nil.
I know I am doing something wrong but I have searched and can't figure out what it is.
Thanks for looking, any help is much appreciated.
edit:
I am trying to access the image from a method inside of the class.
- (void)save {
if (self.image != nil) {
// do some stuff
} else {
NSLog(#"image is nil");
}
}
And it is always coming up nil.
edit 2:
Thanks again everyone. I figured out what the problem was. I was overriding the setters/getters which was causing the issue.
Is it a .png file? Try doing it like this:
UIImage *image = [UIImage imageNamed:#"Test.png"];
So I know there a bunch of questions like this but none of their solutions seems to be helping me.
Let me start of by saying I am using storyboards so I would use initWithCoder instead of initWithNibName:.
Now that we got that bit out of the way. So, simply I want to pass an object to another view with a custom initializer.
So in my second view I would have code like this:
- (id) initWithMyLifeChangingObject: (MagicType *)object {
//Apparently this is important
self = [super init];
//Do some stuff with my magical object
//You know the story
return self;
}
And as the story goes you need to call your world class init:
[SecondClass alloc] initWithMyLifeChangingObject:object];
But initWithMyLifeChangingObject: isn't recognized and gives me a build error saying it is not in existence... so what do I do.
Coming from a .NET background, I used to make classes that looked a lot like this:
MyClass
Inherits List(Of SomeOtherClass)
I am getting smoked trying to do this in Objective-C. I am wanting to have a class that is a collection of UIImageViews.
I tried this, which is wrong (it inherits from NSArray):
- (id)init
{
//I know I'm not using an imageview here, this was just a proof of concept
self = [super initWithObjects:[UIImage imageNamed:#"btnSideMenu"], nil];
if (self) {
}
return self;
}
The collection is a fixed size, so it won't need to be mutable. However, if using a NSMutableArray provides more syntactical sugar than I would not be opposed to it.
I think a subclass for this is excessive. Subclasses should be used to add functionality to a super class. You should just make an NSMutableArray of UIImageViews
I'm going to have objects, read from a .csv (Comma seperated file) which contains file names, later. Thats why i'm trying to do it like this.
What I would like to accomplish is to have the button get the image from the filename in the csv.
What i've tried so far:
The Object:
#interface question : NSObject
{
#private
UIImage *imageName;
}
#property (nonatomic, retain)UIImage *imageName;
(I have tried with NSString aswell as UIImage, neither works like I want them)
ViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
question *question1 = [[question alloc]init];
[question1.imageName initWithContentsOfFile:#"Default.png"];//Will be read from a csv later on, just typing it in manually for a test
testImage = question1.imageName;
}
-(void)imageshow
{
//(UIImage *)testImage;(NSString *)imageNameString; Didnt work
//[self.testImage initWithContentsOfFile:#"%#",questiont.imageName]; - Doesnt work either
[testButton setImage:testImage forState:UIControlStateNormal];
}
-(IBAction)test:(id)sender
{
[self imageshow];
}
Where this code fails is when I press the test button, nothing happens (not crash)
How can I do this properly?
(Add an image with a text filename to a NSObject and then show it in a button/image view)
question1.img = [UIImage imageNamed:#"Default.png"];
[testButton setImage:question1.img forState:UIControlStateNormal];
and yes you can try the following for dynamic images
question1.img = [UIImage imageNamed:[NSString stringWithFormat:"%#",imgName]];
imgName => is the name of the image not the image
example: "abc.png" or "123.png" ,etc
if your property is named imageName the accessor variable is automaticly named _imageName.
You are using two different variables in your code.
#interface question : NSObject
{
#private
UIImage *_imageName;
}
#property (nonatomic, retain)UIImage *imageName;
imageName is not a great name for an property that contains an image.. it would better fit to a string.
There are some things to change.
For mere conventional reasons write all class names with an upper case at the beginning. It eases reading, exchange in forums as SO and avoids mistakes.
Second name variables either speaking or abstract, preferrably speaking. But to not choose a mislieading name such imageName. There should be a name in that variable, not an image, or maybe the graphic that displays a name. :)
imageWithContentsOfFile expects a fully qualified file name. If "Default.png" is part of your boundle, as I guess by its name, then imageNamed:#"Default.png" would do.
Your setImage looks nearly good. It cannot work of course while your image is (null). However, it is not good business practis accessing the iVar direct at this point. You shoudl use its setter/getter. Use instead:
[self.testButton setImage:self.testImage forState:UIControlStateNormal];
In your case it does not make much of a difference. But similar to the other conventions it helps avoiding errors when ever you mix your code with some code that you found on the web or when you work in a team.