Adding custom protocol to UITextField - ios

I have some forms for the authentications and signup views and I want that all UITextField inside those forms have a UIButton as an accessory view, just above the keyboard. I want to have the possibility to set the title and the action for this button
Because I want all those text field have one and each will have a title and an action, and to avoid redundancy, I thought about a protocol.
I want something like extending a custom protocol, for example UITextFieldAccessoryViewDelegate and to be conform to some functions like :
-buttonAccessoryView title ... -> String
-didClickOnAccessoryViewButton.. -> ()
My mind is closed. Someone can give me some ideas to do what I want ?

You could use associated objects to solve this problem. This lets you add a property and its synthesized getter/setters.
#interface UITextField(AccessoryButton)
#property(readwrite, strong, nonatomic) UIButton *accessoryButton;
#end
#import<objc/runtime.h>
#implementation UITextField(AccessoryButton)
-(UIButton*) accessoryButton
{
objc_getAssociatedObject(self, #selector(accessoryButton));
}
-(void) setAccessoryButton:(UIButton *)accessoryButton
{
objc_setAssociatedObject(self, #selector(accessoryButton), accessoryButton, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
Include this category into your forms that need the UIButton for the text fields. Then assign action and title to a UIButton like how you normally do.

Considering everything you want to do I think you are better off using a subclass of UITextField rather than an extension.
Extensions can't add instance variables to the objects they extend, but subclasses can. As lead_the_zeppelin points out in his answer, you can use associated objects to simulate adding instance variables with an extension but it seems like you're making it needlessly complicated when a subclass gives you everything you want.

Related

Can we have data/custom attribute for buttons in ios?

Hello there im basically from web development i have a requirement where i have to send a unique alpha numeric value from one view to another view on click of the button is their any way around we can set custom attribute or data attribute for buttons in Ios one like in htm5 ?
The easiest method is to subclass UIButton.
#interface MyButton : UIButton
#property (strong) NSString *myCustomData;
#end
#implementation MyButton
#end
You could also override the look of the button within this custom class to apply the same button style to all your buttons at once.

Extending a method applicable to all UIButtons

I have a UIButton object in my program.
I want to use it like follows
myButton.setImage:blablabla
mybutton.title:.......blabla
...
...
myButton.placeTextBelowImageWithSpacing:12
While calling my method "placeTextBelowImageWithSpacing:12" it must set the image and text accordingly. I have the method ready with me. How can i use it in the above way.
PS: I hate subclassing.
Thanks in Advance
Create a custom subclass of UIButton. I created a button called FinderButton that has an image and a title centered below it. It works great.
If you hate subclassing then you might want to think about a different line of work.
Being an Objective C programmer that hates subclassing is a bit like being a surgeon who hates blood or a farmer who hates dirt. Defining a class hierarchy is one of the main tools for doing development in an OO language like Objective-C.
You can do this by creating a UIButton category:
UIButton+MyCustomMethod.h
#interface UIButton (MyCustomMethod)
- (void)placeTextBelowImageWithSpacing;
#end
UIButton+MyCustomMethod.m
#implementation UIButton (MyCustomMethod)
- (void)placeTextBelowImageWithSpacing
{
// ...
}
#end
You can't. That isn't valid syntax in Objective-C. The closest you can get to that would be to explicitly declare new properties on UIButton that followed your naming convention. Using them would then look like:
myButton.setTitle = #"something"
Then you could override setTitle's setter (setSetTitle:), and making it call setTitle:forControlState:, which I'm assuming is your goal.
But this should only be done through subclassing (learn to love it, it's a big part of OOP), although if you really really want to, you can add the properties in a category using the Objective-C runtime objc_setAssociatedObject() function more info here: Objective-C: Property / instance variable in category

Any gotchas with objc_setAssociatedObject and objc_getAssociatedObject?

I’m looking into ways to add a property (an integer in this case) to all UIView instances, whether they are subclassed or not. Is using objc_setAssociatedObject() and objc_getAssociatedObject() within a category the appropriate, Apple-endorsed way to do this?
I have heard some concerns that this constitutes a “runtime hack,” and can lead to problems that are difficult to track down and debug. Has anyone else seen this type of problem? Is there a better way to add an integer property to all UIView instances without subclassing?
Update: I can’t just use tag, because this needs to be used in a code base that already uses tag for other things. Believe me, if I could use tag for this, I would!
Associated objects come in handy whenever you want to fake an ivar on a class. They are very versatile as you can associate any object to that class.
That said, you should use it wisely and only for minor things where subclassing feels cumbersome.
However, if your only requirement is to add an integer to all UIView instances, tag is the way to go. It's already there and ready for you to use, so there's no need for involving run-time patching of UIView.
If you instead want to tag your UIView with something more than an integer, like a generic object, you can define a category like follows.
UIView+Tagging.h
#interface UIView (Tagging)
#property (nonatomic, strong) id customTag;
#end
UIView+Tagging.m
#import <objc/runtime.h>
#implementation UIView (Tagging)
#dynamic customTag;
- (id)customTag {
return objc_getAssociatedObject(self, #selector(customTag));
}
- (void)setCustomTag:(id)aCustomTag {
objc_setAssociatedObject(self, #selector(customTag), aCustomTag, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#end
The trick of using a property's selector as key, has recently been proposed by Erica Sadun in this blog post.
Use tag. That's what it was meant for.

Changing value of an object from a different class

I have a ViewController.m with a UIButton and a UIWebView on it.
I've subclassed UIWebView to a class that is now called MyWebView.m.
What is the most efficient way to change the UIButton outlet location value from a method that is inside MyWebView.m
I thought about NSUserDefaults but it feels to me like it's the worst way to go.
Another thought was to copy the next line and also add it inside MyWebView.h:
#property (weak, nonatomic) IBOutlet UIButton *myButton;
and connect it to the button from ViewController.m but I'm also not sure if that's a right thing to do.
What does the button title represent, conceptually? Decide that, and expose it as a string property of your web view and then have your view controller observe the property with key value observing. Or alternatively, extend UIWebViewDelegate with your own protocol, and have the view controller set itself as the web view's delegate. Then have the web view notify its delegate that this value changed.
You can use the app delegate class for persisting the data through the application but this is also not recommended by the good programmers.
One other way is to use Singleton class . This creates only one object per application session so you can use the the value throughout the application also you can modify and access the value. This is the pure approach to go .You can take a look at http://www.galloway.me.uk/tutorials/singleton-classes/

How to make My UIControl subclass as superclass of programmatically created UIElements?

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.

Resources