How to subclass a uibutton and use a standard system image - uiview

I would like to subclass a uibutton and redeclare a couple properties, but i don't want to change anything else. namely, I want to keep the standard plain system image provided.
is this possible or an attempt to eat cake and have the cake it tomorrow?

Yes it's possible. If you want to redeclare use subclass if you want to add more functionality use Categories

Related

Can we access the objects in Storyboard by ObjectID

I have a bunch of static objects (UILabel, buttons, views) in multiple Scenes. They are not connected to any IBOutlet. But I'd like to access them at appdelegate (or first VC), and change their properties before it is loaded.
Anyway to do this?
EDIT: Adding my intention:
I actually wanted to make a custom "multi-language" app. I want to be able to change language from within the app. I can get a list of all the objects by applying built in localization of storyboard (Main.strings is autogenerated). Then I disable localization again. Then from this autogenerated file, I want to be able to connect it to a json data based on language that I select.
Of course you can. For example, you can use tags of UIView. Just set tags in Storyboard. It's easy but not so good. Another way to do this is using Accessibilities. Enable and set for it in Storyboard.
And then you can access it by accessibilityIdentifier property.
I will post my choice of "solution". So what I did was make use of accessibilityIdentifier to set the "key" for the multilanguage phrase translation purpose.
And I make use of the UIView+Recursion class (you can find this simple class somewhere in SO), and basically iterate all the objects in a particular Scene and if the text matches, set the key in accessibilityIdentifier property (either in viewDidload or viewWillAppear or viewDidlayoutSubviews).
This way you can have language changes "on-the-fly" within the app, without restarting.

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

Objective-C way or compiler directive to force a class file include a method without adding a protocol?

I have a custom singleton MyColors class to easily change colors of some buttons easily in many UIViewControllers at the same time.
I put #import "MyColors.h" in every class I need to get color of a button.
Everything works perfectly and setting a the color value in MyColors, that color is applied correctly to where I want.
Now, I want to change colors alive. So I send a NSNotification with name "COLORS_CHANGED".
So every class will observe that and apply colors immediately.
What I want to do is:
Force XCode to remind me that the .mfile that includes MyColors.h must also include colorsChanged method for observing. So, this will prevent me forgetting to add observer
OR:
Add something like a Category or something like that into MyColors.h to do this kind of thing...
What I don't want to do:
I don't want to create a protocol and add it as delegate to header files of every .mfile that includes MyColors.h. Because I can forget that too.. If not, this would be the way ofcourse...
So, I am trying to find an Objective-C way to do this, or a compiler way that works with XCode to do this.
Thank you for sharing your ideas.
Update: I use color values for anything that needs colors not just buttons.
implement this functionality in a base class and make all your UIViewController-s inherit it. i.e - in the base class register for this notification and change the common objects' colors and also call there a virtual method for the inheritors to change their extra objects' colors.
Good luck,

Subclassing vs Category with Interface Builder

I have read multiple times that we should not subclass a component (a UIButton for example) :
Why shouldn't I subclass a UIButton?
Subclassing a UIButton
The problem is when I use Interface Builder.
For example, I have a button with a precise appearance in a lot of my views. I can set them each time with IB (it's painful), or I can use a custom class to factorize the custom behavior and appearance.
It seems a bit contradictory to me that the only way to simplify the process with IB is to do it the way that everybody recommends against.
Is there a better solution ? Can I use a category with IB ?
Thanks.
You might be able to use the UIView appearance proxy. I don't know what all you're doing to your buttons but this might help:
Put this is your AppDelegate file in the application:didFinishLaunchingWithOptions: method
if([UIButton conformsToProtocol:#protocol(UIAppearanceContainer)]){
[[UIButton appearance] setBackgroundImage:[UIImage imageNamed:#"YourImage"] forState:UIControlStateNormal];
//modify any other UIButton properties you want to set globally
}
The second link you provided was pretty clear, and this is pretty much what apple itself states, subclass, but never mess with the internal structure.
Best example is iOS 7, now things are completely different and, for example, an application I'm maintaining had a subclassed UIControl, and now it has trouble running on the new iOS, simply because, it was built with assumptions on how the internal structure works (iterating the internal subviews replacing some things). You might not get your app rejected, but it will be a pain in the a** to maintain.
As a rule of thumb, anything you can do to an UIButton from the outside, something like this:
[myButton setBackgroundImage:... forState:...];
[myButton setTextColor:... forState:...];
myButton.titleLabel.font = ...
You can move it to the inside of a custom subclass method:
+ (UIButton*)fancyPantsButton
{
UIButton *button = [UIButton butonWithType:UIButtonTypeCustom];
[myButton setBackgroundImage:... forState:...];
[myButton setTextColor:... forState:...];
myButton.titleLabel.font = ...
return button;
}
You can also do this on init or awakeFromNib without problems (and I usually prefer the later).
UIAppearence is also an option, as was suggested by user hw731. Whatever floats your boat, really.
As for the second question, nib files pretty much create instance a class and then fill-in the things it stores using setValue:forKey: when loading (that's why you get an error like "class is not key-value compliant for something" when you screw up a nib), so if something is categorised when the nib is being loaded, then yes, nibs respect categories, as its simply using initWithCoder.. and then filling in the gaps.
And, by the same token, the nib file won't be able to fill-in custom properties, since it doesn't know about them, unless you explicitly add them on the "User Defined Runtime Attributes" in IB (iOS 5 onwards).
Another technique for nibs, is using
#property (strong) IBOutletCollection(UIButton) NSArray *buttons;
And then iterating and customising buttons accordingly (be it via a subclass, category, local method, ...). This method is really helpful if you want just a handful of custom buttons, but not enough to warrant using a subclass.
I don't see any reason that you shouldn't subclass UIButton, especially for your purpose of making configuration with IB easier. Neither of the links you provided explain why you shouldn't subclass, so their assertions don't seem reliable. On the other hand, the presence of UIButtonTypeCustom in UIButton.h gives the impression that the framework authors planned for UIButton subclasses.

Select a range in UISlider

i asked me whether it is possible if i can create a uislider who has 2 handles to select a range. Just like here:
The problem i am facing is that i dont want to use a custom UIControl Subclass. I need a UISlider subclass or a other solution for this problem, because a lot of the code is based on UISlider specific propertys etc. So is there any possibility to achieve this ?
Look at the following example:
http://www.cocoacontrols.com/platforms/ios/controls/rangeslider
You can subclass UISlider, but it will be very difficult. Your class should offer quite some new properties, and the old ones won't make much sense at all.
Not sure how your code can be based much on UISlider specific things - as everything would change the meaning (i.e. ranges instead of one value).
If you really need a common base class, you could encapsulate ("has-a" relationship) the control in a custom class and let this handle the different types.
I implemented a similar control using a custom view, and it happened to be quite straight forward.
UISlider doesn't provide the functionality you're after, and subclassing UISlider probably won't work out. What would the value of such a control be? The value of a slider is a number, but you want it to be a range. Consider a custom control that duplicates the UISlider properties you need.

Resources