I have a UIView subclass. The view has a float property. I initialize this subclass from another view (it's superView) like so:
myView = [[CustomView alloc]initWithFrame:aFrame];
The problem is, I am confused about how to assign values to myView's float property. When I try to assign a value just after initializing (from the superview's initWithFrame), nothing happens. Even when I try to to assign from another method or from the viewController it does not work.
Thanks for reading!
Most likely your class is trying to use it in a method that is called before you set it. Make a custom initializer such as -(id)initWithFrame:(CGRect)frame andFloat:(float)f. This will allow you to set the float when the object is created, so it will have that value upon instantiation. If this is not the issue, we will need to see more code!
Related
I have a view controller with properties that determine its behaviour. These are set by its parent in prepareForSegue.
The potential bug this induces in my program is that the parent in question is not guaranteed to set the properties, so I would like to have a default value. On researching, I now understand that properties in Objective C don't have default values. This left me with the following options:
Set the default values for properties in the child view's viewDidLoad method. However, on investigation, viewDidLoad is called after prepareForSegue in the parent - so I would be overwriting the parent's values when the parent actually does set the properties.
I then thought I could use (id) init to initialize the values, but, at least when using storyboards, this method isn't called at all!
I may have a workaround in that objects will initialize to a default value, but in this case all I want to pass in is a BOOL. And since the bool will have some value even if not initialized correctly, I can't test it to see if it is non-nil.
Are there any opportunities for initializing value in the child view controller before prepareForSegue in the parent?
Overriding init will not help as it is not the designated initialiser for UIViewController objects. When manually instantiating a view controller - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle is called, when loaded from a storyboard - (id)initWithCoder:(NSCoder *)decoder will be called. If you want to set properties when the view controller is initialised you have to override both initialisers.
On researching, I now understand that properties in Objective C don't have default values.
They do. nil for objects, 0 for integer values, 0.0 for floating points etc. If you need default values other than that you should set them in the appropriate init method.
I'm trying to get a handle on what's happening in my app...
I have a UICollectionViewCell subclass which has a UIImageView as a property.
In that subclass's init method, I programatically add the imageView property as a subView of the classes contentView:
[self.contentView addSubview:self.imageView];
At the point this happens, the 'self.imageView' property is null as the imageView has not been created and assigned to the property yet.
Later in my cellForItemAtIndexPath method, I assign the imageView property of the cell equal to an imageView object.
At this point I expect that the content view would now have a valid imageView subclass, but that's not what i'm seeing.
So my question is: Why doesn't it work?
Should I be able to add my 'null' property imageView as a subView of my self.contentView and then later assign the imageView property equal to an imageView object, and then see that object as one of the contentViews subviews?
I hope this question makes sense, it was a pain to describe!
Adding a subview which is nil sounds wrong to me
I think you are using a wrong approach. You should instantiate and add your imageView in your cellĀ“s init method and then, in the cellForItemAtIndexPath of your controller assign the image like this
cell.imageView.image = the image you want...
No, you shouldn't (and you see it doesn't work). A property is a reference to an instance of something. If that instance doesn't exist yet then you can't work with it. Trying to isn't setting up some rule for future use, it's just quietly doing nothing.
You can add a method like configureImageView: and call that instead. The implementation would set the property and add the image view as a subview.
I have a view controller with properties that determine its behaviour. These are set by its parent in prepareForSegue.
The potential bug this induces in my program is that the parent in question is not guaranteed to set the properties, so I would like to have a default value. On researching, I now understand that properties in Objective C don't have default values. This left me with the following options:
Set the default values for properties in the child view's viewDidLoad method. However, on investigation, viewDidLoad is called after prepareForSegue in the parent - so I would be overwriting the parent's values when the parent actually does set the properties.
I then thought I could use (id) init to initialize the values, but, at least when using storyboards, this method isn't called at all!
I may have a workaround in that objects will initialize to a default value, but in this case all I want to pass in is a BOOL. And since the bool will have some value even if not initialized correctly, I can't test it to see if it is non-nil.
Are there any opportunities for initializing value in the child view controller before prepareForSegue in the parent?
Overriding init will not help as it is not the designated initialiser for UIViewController objects. When manually instantiating a view controller - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle is called, when loaded from a storyboard - (id)initWithCoder:(NSCoder *)decoder will be called. If you want to set properties when the view controller is initialised you have to override both initialisers.
On researching, I now understand that properties in Objective C don't have default values.
They do. nil for objects, 0 for integer values, 0.0 for floating points etc. If you need default values other than that you should set them in the appropriate init method.
I am sub-classing a UIScrollView element in response to a previous question suggestion.
In my subclass I have a few methods that are triggered by touch and keyboard events. Those events need to interact in various ways with variables that are in my superview.
I've tried accessing them via _myVar.text = #"smth" but that doesnt compile.
I know I could play back and forth with NSNotifications but is there a way to access the variables in my superview / class from my UISCrollView subclass?
I've tried self.myVar = #"" but it says that it is not recgonised. I am subclassing an UIScrollView element but then my view that hold all my variables is a UIViewController. just the UISCroll element was subclassed
Everything that is a #property in your superclass is accessible in your subclass, but not in the other way
It sounds like you're a little confused here. Are you sure you're talking about the superview? Or are you talking about the superclass from which you derived your subclass? If superview, and if you know the type of the superview, get a pointer to it, cast it to the appropriate class type, then call methods on it or access its visible properties.
UIButton* superButton = (UIButton*)[self superview];
superButton.visible = NO; // Assign to superview property
If you're talking about the superclass (in your case UIScrollView), then yes of course you can use any of its visible methods and properties.
self.bounces = YES; // Assign to superclass property
In case it's not clear what the difference is, you should really do some more reading about the basics of Objective-C and object oriented programming.
Superview: the view relative to which this view is laid out. This view is a subview of the superview. UIView and all derived classes have this hierarchical relationship.
Superclass: the class whose functionality you are extending to define your subclass. Your subclass inherits all visible properties and methods.
So much confusion, where to start? I really don't know. For what it's worth,
_myVar.text = "#"smth"
will obviously not compile, note the stray ".
_myVar.text = "#smth"
has a better chance of compiling.
My question relates to Assignment 3 in CS193p.
Im having a terrible time getting drawRect in my View to receive information passed from my View Controller. Basically, my goal is to pass view-specific information (like self.view.size.width) to the controller, have it make some modifications (like result = self.view.size.width * 2), and pass result back to drawRect so that it could take the new info and draw it. Im pretty sure I have my delegation set up correctly, and really have tried a list of potential work-arounds:
make a public View #property, which I access in my controller.m via
View *newView
someResult = newView.variable
which I would then try to access from my view.m via
self.variable
use methods set in my View's #protocal, which I try to pass data via myView.dataSource someMethod:someData
But so far none of these are currently working (i.e. my self.variable would always come out to be 0, which shows that no data was passed to it). Your help much appreciated!
UPDATE:
The culprit was that, in the storyboard, I didn't control-drag the View Controller to the View, and hence the Controller was never connected... but at least now it works. ^_^
View *newView someResult = newView.variable is not valid syntax.
If newView.variable is not of type View then that is a problem.
If newView is already declared, you would access variable using int myValue = newView.variable (that is, asuming it is of int type).
An example would be:
// Somewhere in your code, you declare your object
UIView *otherView = [[UIView alloc] init];
// Somewhere else, you set a variable of your object
otherView.backgroundColor = [UIColor blackColor];
// Again, somewhere else you want to access that value
UIColor *thatColor = otherView.backgroundColor;
I hope this explains it well enough.
Is this the correct description of what you want to do? You have a view controller (presumably the calculator type view controller from the course) and you want to communicate between that view controller (whose view has the calculator buttons) and a view other than it's own?
If so, here are the steps you should take:
In your view that you want to receive information from a delegate:
Declare an #protocol with the method you want the delegate to implement. Declare a property in the header file of the view that conforms to the aforementioned delegate: #property (nonatomic, weak) delegate<NameOfTheProtocol> delegate;
In the view controller you want to act as the delegate, declare it conforms to the protocol: MyClass: UIViewController <NameOfTheProtocol>. In the implementation file of that view controller, implement the methods of the protocol. Where ever you create the view that you want to receive information, set it's delegate property to your view controller.
To pass information between them (I have no idea what information you want to pass), your protocol method might be something like: -(CGPoint)pointToDrawAtGivenPosition:(CGPoint)point
In your view that has the delegate property, you could in drawRect do something like:
CGPoint pointToDrawAt = [self.delegate pointToDrawAtGivenPosition:CGPointMake(100, 100)];
//Now draw that point or whatever.
Basically, the view is asking its delegate to make a decision about where to draw something. It passes some information to the delegate, and the delegate responds with the correct position for the view to draw at.