In my application I want to associate NSMutableDictionary to all UIElements (UIButton, UILable, etc), I can easily achieve this by subclassing each element, but I just want to know if I can make my own UIControl subclass -with a property of type NSMutableDictionary-, as superclass of all programmatically created UIElement s in anyway, so that I can reduce the number of subclasses.
Here like this
#interface UIControl : MyControls
{
}
#property(nonatomic,retain) NSMutableDictionary *details;
#end
and make MyControls as superclass of all programmatically created UIElements
You can do this, not by subclassing, but by adding your own properties and methods to UIControl itself (the superclass of UIButton, UILabel, etc.). These will then be inherited by any standard buttons, labels, etc. that you instantiate. Objective-C lets you add your own methods very easily using Categories. However, you can't add instance variables via categories. To do that, you need to use Associative References which are documented in the Objective-C Runtime Reference.
There's a good tutorial on how to do this here.
By the way, I don't necessarily disagree with inturbidus. But if you're sure you want to go this route, that's how you'd do it.
Related
I would like to be able to interact with the UIControl I have made, and therefore want it in my ViewController.
What I tried
I subclassed UIControl (1).
Then I added a UIView to my View Controller and assigned it the new class (2).
But in Interface Builder I am not able to set my outlets to the buttons contained in the new class (1)?!
1:
2:
UIControl's documentation confirms that it is a subclass of UIView, and I should therefore be able to connect the outlets, right?
What am I missing here? :/
Off-course you can't add IBOutlet because buttons what you added to WeekdayControl are in UIViewController, you can't add Outlet to WeekdayControl, buttons only subviews of WeekdayControl, UIViewController is boss here, and you can add outlet only to UIViewController. (Sorry for my English)
Better create you buttons programatically in WeekdayControl.
Must read first:-
You cannot use the UIControl class directly to instantiate controls.
It instead defines the common interface and behavioral structure for
all its subclasses.
The main role of UIControl is to define an interface and base
implementation for preparing action messages and initially dispatching
them to their targets when certain events occur
So, you are doing wrong, if you really need to make a custom view or custom control then you can directly do it by creating a custom UIView and connecting the outlets directly with the view.
I think you missing the objective of subclassing a UIControl, it doesn't give rights to create outlets as it's a subclass of UIView,just read this lines what it is stated in the docs:-
Subclassing Notes
You may want to extend a UIControl subclass for either of two reasons:
To observe or modify the dispatch of action messages to targets for
particular events
To do this, override sendAction:to:forEvent:, evaluate the passed-in
selector, target object, or UIControlEvents bit mask, and proceed as
required.
To provide custom tracking behavior (for example, to change the
highlight appearance)
To do this, override one or all of the following methods:
beginTrackingWithTouch:withEvent:,
continueTrackingWithTouch:withEvent:, endTrackingWithTouch:withEvent:.
As we all know the inheritence hierarchy of UILabel is:
UIView : UIResponder : NSObject
Now I want to change the UIView in the hierarchy to my custom UIView like:
CustomView: UIResponder : NSObject
So that all UILabels in my app Will have my custom UIView in their inheritence hierarchy.
That is not possible.
However, you can look for extending your class using a category.
A category allows you to add methods to a class, but does not allow to change them.
Here is a tutorial:
http://www.tutorialspoint.com/objective_c/objective_c_categories.htm
Depending on what you are trying to achieve, subclassing UILable may still be an option. What exactly are you up to?
Edit: Well, theoretically it is possible chaning an object's superclass during runtime. However, I am not sure whether I really should recommend that to somebody who just asked your question. It is rather advanced, if advisable at all, and should be done by programmers who know exactly what they are doing.
However, see this questions and answers:
My isa-swizzling breaks KVO
Dynamically change an object's superclass
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.
I'm working on an accessibility project for an iOS application. Because accessibility does not act quite as advertised, I have to override accessibilityFrame, accessibilityActivationPoint and pointInside:withEvent in a subclass in order to expand the region recognized by VoiceOver (for both drawing and touch recognition) beyond the "natural" bounds of the control view. So, in order to change the VoiceOver bounds of a UIButton I have to subclass that class and then add these three methods. In order to do this for a UILabel I have to add another subclass with the code, and so on.
I can refactor the code in these methods to a central location, but I was wondering if this can be done more elegantly with inheritance. I'd like to put this code into a subclass of UIView (maybe called UIViewAccessible) and then create a subclass of UIButton called UIButtonAccessible which inherits from UIButton which would in turn inherit from UIViewAccessible instead of UIView. Is this possible, or can something like this be done with a category?
Edit: According to the docs, you can't really achieve this with a category:
If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime.
Is there some other way to do this?
To answer your question, no, it can't, since your UIViewAccessible is a second degree sibling to UIButton in the inheritance chain (both inherit from UIView at some point). But I guess you already knew that. As for a solution, you could wrap around your UIView accessible classes a decorator and use protocols for strong typing. That way you'll keep the code in one place. I've described this technique here in more detail (although for a different purpose, it's the same situation).
For the views that would support accessibility you'll have to do this:
#property (nonatomic, strong) UIView<MyAccesibilityProtocol>* view;
//self.view can come from the nib or previously created in code
self.view = [[AccesibilityDecorator alloc] initWithDecoratedObject:self.view];
//you can then use self.view like any other UIView,
//and because it also implements an
//accessibility protocol, you can use the methods
//implemented in the wrapper as well.
//more than that, you can control which methods to override
//in the AccesibilityDecorator class
[self.view addSubview:otherView];//could be overridden or not
[self.view myAccesibilityMethod];//custom method declared in the protocol
In many iOS books and tutorials they demonstrate how in interface builder you can basically turn a UIView into a UIControl and have it inherit new higher level functionality to respond to clicks and behave like button for example. This is done simply by changing the class type in interface builder of a selected UIView.
This is often done to dismiss the keyboard when someone touches on the "background" or main view of a given view controller. Once a UIView's class is changed to a UIControl you just assign connect a new IBAction for when a TouchUpInside event occurs for example.
Now I understand this concept but it seams like a weird Xcode hack. The reason is, I don't see how I could accomplish the same thing programatically. Let me explain: If I create an instance of a UIView in code and I want it to behave like a UIControl how would I tell this UIView instance that I want it to inherit from UIControl. Now keep in mind I don't actually want to subclass UIControl because that would be jumping through more hoops and I don't think that is what Interface Builder is doing when you change that class type, or is it? Also, keep in mind UIControl is meant to be an abstract class and not to be used directly otherwise I would probably just do that.
Ultimately my question is, is there an equivalent way to accomplish the same thing in pure code and have a UIView become a UIControl such that I can assign the higher level events to it?
I hope this makes sense, if not I can elaborate.
UIControl inherits from UIView, so if you wanted to do this programmatically, you would just create an instance of UIControl instead. So if you were creating a view controller's view programmatically, for instance, you could do something like:
- (void)loadView
{
CGRect viewSize = /* some appropriate default size */
UIControl* myControlView = [[UIControl alloc] initWithFrame:viewSize];
// configure your control (e.g., set events, etc)
[self setView:myControlView];
[myControlView release]; // omit this line if using ARC
}
I created xib file. then new Objective c class file inherits from
UIView. i set xib class Objective c class, in interface builder and
then change super class of Objective c class to UIControl.