in -init method won't change subviews - iphone

I have a object derived from UIView, it is AIItem, this item have UIImageView *status_view, now I need another object AIAnotherItem derived from AIItem, problem is in status_view.
For Example :
AIItem init method
-(id)initWithName:(NSString *)name {
self = [super init];
if (self) {
status_view = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,50,50)];
status_view.image = [UIImage imageNamed:#"item_image.png"];
[self addSubview:status_view];
}
}
AIAnotherItem init method
-(id)initWithName:(NSString *)name {
self = [super initWithName:name];
if (self) {
status_view.image = [UIImage imageNamed:#"another_item_image.png"];
}
return self;
}
in AIAnotherItem I set another image to status_view but it won't changed.
Question is why ? and how do this ?

Regardless what the mechanics are of this not working (I am sure you will figure it out), I believe that you are perhaps not going about this the right way.
Would it not be more logical to have class AIItem.h that has an empty property statusView? And then two derived classes (or instances of the same subclass) that inherit the same statusView but fill it with different images?
I think this would correspond more closely to the philosophy behind inheritance.

Related

How to set NSString before calling a method objective c

It might be a simple question yet I could not figure out what I am missing.
In ViewControl.h I declared UIColor
#property (nonatomic, strong) UIColor * myColor;
In ViewControl.m I have a method that do something and return new UIColor
#synthesize myColor = _myColor;
In ViewDidLoad Method
- (void)viewDidLoad
{
myColor = [UIColor RedColor];
}
-(void) ShowColorPopUpView
{
if (!self.wePopoverController)
{
ColorViewController *contentViewController = [[ColorViewController alloc] init];
contentViewController.delegate = self;
self.wePopoverController = [[WEPopoverController alloc] initWithContentViewController:contentViewController];
self.wePopoverController.delegate = self;
self.wePopoverController.passthroughViews = [NSArray arrayWithObject:self.navigationController.navigationBar];
[self.wePopoverController presentPopoverFromRect:self.tvTweetDetails.frame
inView:self.view
permittedArrowDirections:(UIPopoverArrowDirectionUp|UIPopoverArrowDirectionDown)
animated:YES];
} else
{
[self.wePopoverController dismissPopoverAnimated:YES];
self.wePopoverController = nil;
}
}
-(void) colorPopoverControllerDidSelectColor:(NSString *)hexColor
{
_myColor = [GzColors colorFromHex:hexColor];
[self.view setNeedsDisplay];
[self.wePopoverController dismissPopoverAnimated:YES];
self.wePopoverController = nil;
}
- (UIColor *) returnColor
{
return _myColor;
}
My Question starts here: I have two methods to change a textview font and background color
- (IBAction)btnFontColorPopUpMenu:(id)sender
{
[self ShowColorPopUpView];
tvTweetDetails.textColor = [self returnColor];
}
- (IBAction)btnTextViewBackGroundColor:(id)sender
{
[self ShowColorPopUpView];
tvTweetDetails.backgroundColor = [self returnColor];
}
The issue now is when I call the method it return it returns RED and if I call it again it returns the the BlackColor.
How Can I call the method and change the Color to the new one and then return it. I want to get the Black color directly.
I want to execute the method first then return the color but what happens is assign the color before execute the method.
I hope I made it the Question Clear.
Okay, I'll take a whack at this.
I suspect you are doing some kind of presentViewController:... method in your color changer method. That's great, but it has implications. The method you call that in continues to execute during that presentation. That means it may return, etc.
This is where the concept of delegates comes in. You may benefit from restructuring the data flows here a bit.
What I suggest (if I am correct about the presentation of a color picker UI) is that you make the following changes:
Create a #protocol ColorPickerDelegate with one method: -(void) userChoseColor:(UIColor *) color
Add a #property (weak) id<ColorPickerDelegate> delegate to your color picker view controller
make your VC here implement that protocol
Inside the delegate method, set your local property
Implement a custom setter for the local propert, and update the background color whenever the color changes.

Inheritance in Objective C

I have a main game class which renders the game using Open GL. Now I thought I could inherit from this class and then just call [super init] in its init method to get a copy of it. The plan was to make some modifications in the copy but as it seems this doesn't work.
The following is the header file of my class:
#import "GameView.h"
#interface CloneView : GameView {
}
-(id)initWithFrame:(CGRect)frame;
#end
And this is the Clone view class:
#implementation CloneView
-(id)initWithFrame:(CGRect)frame{
return [super initWithFrame:frame];
}
#end
If I set a break point in the init method in the GameView class it stops there. Thing is: my clone view doesn't get rendered, the screen stays black.
What am I missing? Thanks for your help!
Edit
Just for the record: I tried without implementing initFrame and got the same result. (as expected as the initFrame as above isn't doing anything apart from calling super)
Edit 2
I'm adding my clone to another view so I'm creating two Eagle contexts. Could that be the reason why it doesn't work?
If you are not adding anything in the init function of CloneView than you don't even have to rewrite it. You can just have your class inherit from GameView and it automatically copies it's init function.
This is from the apple docs
You should assign self to the value returned by the initializer because the initializer could return an object different from the one returned by the original receiver.
So Try doing this
-(id)initWithFrame:(CGRect)frame{
if(self = [super initWithFrame:frame] ) {
//Do whatever you need to do here.
}
return self;
}
This should fix your issue if you need to do something in your init method. Otherwise you can skip the init method altogether.
try doing this it may work..
return(self=[super initWithFrame:frame])
which ensures the super class method is copied properly to the current method
TNQ
I finally located the problem:
I needed to write a second init method. The problem was that the following code was being executed twice:
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)[super layer];
[eaglLayer setOpaque:YES];
m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!m_context || ![EAGLContext setCurrentContext:m_context]) {
printf("FAIL \n");
[self release];
return nil;
}
[Textures loadTexture];
if ([self createFramebuffer]) {
[self draw];
}
This code was in the initFrame method of the game class. I made a second init method that does not execute this code. Instead, this code is executed in the parent view class of the clone. Now it works, YAY!!
Thanks for trying to help me!

shared method to update Core Data NSManagedObject?

I am looking for a basic pattern where I can move some shared code. I have an NSManagedObject PurchaseOrder which is stored in Core Data. This can be edited and changed in several different views. Most of the time it is always the same type of change, PurchaseOrder is updated with data from another NSManagedObject Client.
I am wanting to move this type of code to a single place so I can call something like:
-(void) updatePurchaseOrder: (PurchasOrder *) aPurchaseOrder withClient:(Client *) aClient withManagedObjectContext: (NSManagedObjectContext *) aManagedObjectContext {
// update code goes here
}
Is this a bad idea or a recipe for disaster? I do have a shared instance class I am using already (small bit of bit below):
static SharedFunctions* singletonInstance = nil;
-(id)init
{
if ((self = [super init]))
{
}
return self;
}
+(SharedFunctions*)sharedInstance
{
#synchronized(self) {
if (singletonInstance == nil)
{
singletonInstance = [[SharedFunctions alloc] init];
}
}
return singletonInstance;
}
Which I call function like this:
[[[SharedFunctions] sharedInstance] myMethod];
This has been working well for me. Thoughts?
Where is your updatePurchaseOrder method defined? In this situation, I would create a custom PurchaseOrder subclass of the NSManagedObject and implement an updateWithClient method.
#interface PurchaseOrder : NSManagedObject {
}
-(void)updateWithClient:(Client *)client;
#end
So you can simply call [aPurchaseOrder updateWithClient:aClient]; where you need to. Seems more OO, unless I'm missing something?
If you've not made a custom subclass for PurchaseOrder, you could do the same thing in a category of NSManagedObject.

Calling -initWithFrame: on super class

Can someone help me understanding as why do we call an initialization method on super first before initializing. I came across a piece of code in a subclass of UIView and wanted to know that here myMethod is always getting called that means I am not getting the frame set in UIView, then why are we doing this and using an if condition.
self = [super initWithFrame:CGRectMake(0, 0, 20, 100)];
if(self != nil) {
[self myMethod:data];
self.backgroundColor = [UIColor clearColor];
}
return self;
Let's say I have a UIView subclass called SpinningView. The code to create spinningView would look like this:
SpinningView *spinner = [[SpinningView alloc] initWithFrame:CGRectMake(0.0, 0.0, 20.0, 20.0)]
Now let's take a look at the implementation of SpinningView's -initWithFrame: method
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.backgroundColor = [UIColor clearColor];
}
return self;
}
The first line is simple assignment. We're assigning ourselves to the result of UIView's implementation of -initWithFrame:
We use the if statement to see if self is even valid. If it's not we just return it. If it is, we configure it.
This is simply calling the constructor of the super class (in this case UIView).
You need to call UIView's constructor to make sure that all the variables you don't see from your subclass is set up properly, and that's what you do with [super init] (or in this case initWithFrame:).
There are a few other reasons why it looks like this.
First of all [super init] might return nil. Perhaps something went wrong initializing things in the code of the superclass. The check for self != nil makes sure you don't use the object when something is already wrong with the object. It might even have been released by the super constructor.
In other cases the super constructor might actually return a different object altogether. Examples of this happening is with class clusters or when you implement a singleton.
To summarize:
Always call the designated constructor (i.e. init-method).
Always use the standard construct of if ((self = [super init])) { /* own init */ } return self;
Sometimes it looks different, but only for special reasons. If in doubt, always use (2).
Apple's documentation has a lot more info on this is you're interested.
Also, when overriding constructors like this, remember that there might be more than one constructor. For instance, if you add the view using Interface Builder, that view will be initialized using "initWithCoder:" instead. All constructors begin with "init" though.

Dealing with objects from different classes

I have 3 classes of objects. All 3 classes share some properties in common, as color, text, etc.
For example, I can have this
Class1 *objectA = [[Class1 alloc] init];
objectA.myColor = [UIColor redColor];
Class2 *objectB = [[Class2 alloc] init];
objectA.myColor = [UIColor redColor];
Class3 *objectC = [[Class3 alloc] init];
objectA.myColor = [UIColor redColor];
... etc.
Now I need, for example, to create a method that can change the color of a given object, whatever class it represents.
A typical method would be
- (void) changeColor:(Class1*) myOBJ toColor:(UIColor*)myColor {
myOBJ.color = myColor;
}
when in fact I need this
- (void) changeColor:(???) myOBJ toColor:(UIColor*)myColor {
myOBJ.color = myColor;
}
// what to put on ??? to make it generic? Is this a "whatever" kind?
thanks
EDIT
the problem of using this approach
- (void) changeColor:(id)myOBJ toColor:(UIColor*)myColor {
if ([myOBJ respondsToSelector:#selector(setColor:)]) {
myOBJ.color = myColor;
}
}
is this. Imagine I want to set the frame of the object.
Then I will have to have this:
- (void) changeColor:(id)myOBJ newFrame:(CGRect)myFrame {
if ([umID isKindOfClass:[Class1 class]]) {
Class1 *oneObj = (Class1 *)myObj;
oneObj.frame = myFrame;
}
if ([umID isKindOfClass:[Class2 class]])
Class2 *oneObj = (Class2 *)myObj;
oneObj.frame = myFrame;
}
if ([umID isKindOfClass:[Class3 class]])
Class3 *oneObj = (Class3 *)myObj;
oneObj.frame = myFrame;
}
}
in other words, I will have to repeat the same stuff 3 times... right?
in other words, the problem is not solved as this is the same of having 3 methods, one for each class.
Maybe you can use protocols? Make Class1, Class2 and Class3 conform to a protocol with a property myColor. Then you could have a method like this (assuming your classes are of type UIView and your protocol is called ColorProtocol):
- (void) changeColor:(UIView<ColorProtocol>*) myOBJ toColor:(UIColor*)myColor {
myOBJ.color = myColor;
myOBJ.frame = ...;
}
Here is what your protocol definition could look like:
#protocol ColorProtocol
#property (nonatomic, retain) UIColor *myColor;
#end
Change your class definition files (.h) as follows to specify that you will conform to the protocol:
interface Class1 : UIView <ColorProtocol> {...}
In the implementation files (.m) you must simply synthesize the myColor property to conform to the ColorProtocol:
#synthesize myColor;
If your classes are very similar, using inheritance might be even simpler though. Check out Philip Regan's answer.
You have a couple options. The simplest, and "most dangerous" approach is to use a type id. This will let you pass in any object, but you'll want to test that it actually has a color property before you try and set it.
- (void) changeColor:(id)myOBJ toColor:(UIColor*)myColor {
if ([myOBJ respondsToSelector:#selector(setColor:)]) {
myOBJ.color = myColor;
}
}
(That said, with the responds to selector check, this approach isn't all that dangerous, and it's much more flexible than the next idea.)
Another approach is to have all your objects inherit from a shared base class that has a color property. Then your parameter type would be the base class. This approach could be considered "safer" as the compiler would check that you're passing in the correct type of object. This approach also requires considerably more code.
If you want to use the first approach, but set something other than color, adjust the respondsToSelector: call appropriately.
- (void) changeFrame:(id)myOBJ newFrame:(CGRect)myFrame {
if ([myOBJ respondsToSelector:#selector(setFrame:)]) {
myOBJ.frame = myFrame;
}
}
In general, if you want to know if an object supports propertyX, use [myOBJ respondsToSelector:#selector(setPropertyX:)]. If the passed in object is declared as id, you can then call [myOBJ setPropertyX:newPropertyValue] or myObj.propertyX = newPropertyValue.
If you have multiple classes that share characteristics, then, if at all possible, I suggest refactoring the class structure so that those characteristics are contained in an umbrella parent class, we'll call it ClassZ. ClassZ's subclasses can override things as needed. Otherwise, let the method in the parent class handle it for you. Then, your method turns back into this...
- (void) changeColor:(ClassZ *) myOBJ toColor:(UIColor*)myColor {
myOBJ.color = myColor; // note, myObj is ClassZ, not the subclasses.
}
Otherwise, you are stuck with id and testing the individual classes.
use [object setFrame:newFrame]; instead of object.frame = newFrame;
and instead of oldFrame = object.frame; use oldFrame = [object frame];
??? will be 'id'.