I want to apply a setting globally (to all text UIViews in my app) - ios

I have a bunch of text views, and I now want to turn autoresizing on in all of them. I don't want to highlight each one individually, and I only want the changes to apply to all text views in the app. So I don't want to modify the framework. I will be sure to pick the best answer.
EDIT: I guess I should have mentioned earlier that I am using storyboards.

In iOS 5.0+, you should be able to use the appearance proxy for UITextView like so:
[[UITextView appearance] setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
This would make all UITextView's respond with a flexible width and height. Here's a great tutorial on how to use the proxy for other UI controls:
http://www.raywenderlich.com/4344/user-interface-customization-in-ios-5
EDITED:
This code should work and I've tested this in both the simulator and on an iPhone directly, even though the autoresizingMask property in UIView.h is not flagged with UI_APPEARANCE_SELECTOR. This post seems to indicate that its possible for a property to not have this flag, yet still obey messages from the appearance proxy. All that said, #rmaddy is right. It might be a risk to rely on this long-term.

One option is to subclass UITextView and create a CustomTextView. In its init methods or layoutSubviews method, set the autoresizing mask and then use that CustomTextView in your project. One advantage with usage of init method for setting this is that, you can later override this autoresize mask.

Related

How to do app-wide / faster updates by UI element type, in Swift using Xcode ...?

Just curious - doing some maintenance on a swift app, bit time consuming, would love to know if there is a better recommended way, or faster way (?), to do mass updates for a UI element type, e.g. update all buttons, to have a certain property, e.g. say a color or width constraint...?
Color, yes, by using the button's appearance proxy, like
UIButton.appearance().backgroundColor = UIColor.whateverColor()
Width constraint, no. There are a couple other ways to do it, though.
If your regex skills are sharp, you can do a search & replace in all of the storyboards' and xibs' XML code to add a width constraint to each, but that'd be error-prone because some of them may already have width constraints.
You can subclass UIButton and give it a width constraint and set any other properties you wish, but you'd still have to search-and-replace all UIButtons in the appearance files with your custom class type.
For some mass updates, like changing fonts or colours of a control, you could use the UIAppearance proxy. You can also extend classes to add more options for controlling the design of views and controls. Just add methods marked with UI_APPEARANCE and implement as needed.

UIButton modifying titlelabel seems to change its frame

Something strange is happening. Basically, I am trying to recreate the messaging app. So when I am trying to get the Send button to change from Grey to blue when the user has typed in at least 1 character.
The problem comes when I am trying to change titleLabel, the button will disappear. Later I found out it reverts back to the old position (when the keyboard it not shown).
Why does it do this? If I do not modify the titleLabel everything works as usual. However, if I do, the UIButton goes back to the original location. If you need any sample code let me know, but I am not sure what to put on here as it's just [self.button.titleLabel setTextColor: [UIColor blueColor]; in the UITextViewdidChange but it's acting strange.
Thanks!
Alan
You might be fighting against auto-layout. I saw similar behavior, and someone answered my question here: Why does UIButton resize when I access titleLabel property?. Basically, I was suggested to forego auto-layout completely or only use auto-layout (never set frames programmatically).
Well as mentioned here by others, you might be "fighting" with auto-layout. You do not have to ditch auto-layout, you could just bind the NSLayoutConstraint to an IBOutlet property, and update the constraint. If you do not have a constraint, then one is created automatically for you - you should create one manually and attach it. If it is created in code, the find it by code and save a reference to it.
You could also go back to the simpler AutoResizing, which was there before auto-layout (and is not deprecated, yet).

Changing the font of every UILabel in a large app

Here's an interesting problem for you:
We are in the process of re-skinning our entire app, which consists of over 100,000 lines of code and almost 100 XIB files. The new design requires (almost) every label in the app to use a new custom font, whereas the old app uses the default font of Helvetica Neue.
What is the most efficient way of changing as many of the UILabels as possible? We don't want to have to manually change thousands of labels both in code and in XIBs (which is especially difficult because we are using a non-system font).
We've discussed swizzling UILabel's creation methods to default to using the new custom font, which would still allow for the few labels that would remain in Helvetica Neue to be customized after creation.
Thoughts?
Take a look at NUI https://github.com/tombenner/nui.
You can customize a lot controls with it using a CSS-like stylesheet and implement it via subclasses or categories.
You should probably subclass UILabel and override either an initmethod of your choice, or awakeFromNib, and set the custom font there. Then you can go through the xib, either manually, or open it up in a text-editor and add a line like
<string key="X.CustomClassName">YourCustomLabelClass</string>
To set the specified label to your custom label class.
Swizzling is a good option . If you want to do it other way and have problems with custom fonts, I usually make a trivial subclass of UILabel that changes it's font in awakeFromNib for each custom font so I can lay them out in the interface builder.
But... This comes to my mind:
[[UILabel appearance] setFont:xxx];
I am not sure how you would deal with keeping the size, though. Perhaps swizzle is the best choice

When do UIAppearance proxy rules get applied to new view controller?

I'm wandering when exactly do UIAppearance rules get applied to some new view controller?
I've made some global rules and I call them in my app delegate. That way all UIButtons look that same. But now I want to modify just appearance of one UIButton. I've tried putting the code to remove it's background inside - (void)viewDidLoad but it's not working - UIAppearance rules aren't applied yet. In one ViewController I put modification code inside - (void)viewWillLayoutSubviews and it worked perfectly, but now in another ViewController it doesn't work (code is the same).
Where is it safe to override UIAppearance rules?
According to the 2011 WWDC video introducing UIAppearance, the customizations are applied right before -layoutSubviews is called on the view.
If you're looking to customise one specific button you should either:
Alter the properties of the button instance directly, and not touch the appearance settings for the class, or
Use the appearanceWhenContainedIn: method like below:
[[UIButton appearanceWhenContainedIn:[CustomView class], nil]
setBackgroundImage:myButtonImage
forState:UIControlStateNormal];
That way you can still use the appearance proxy for your specific button (when you know it's contained in a specific view), and not alter the general appearance settings.

UIScroll and its nested elements

I created a UIScrollView.
I set up the dimensions and then I am trying to add UILabels.
However the labels are all white text (annoying because I have to change the property per label).
Is there a way to make all labels (new ones that are dragged from IB to the view) have a default text color of black?
Edited to match comments
I want to use IB as much as I can. Therefore I want to drag UILabel from the Library palette to the UIView. When I do this, the UILabel is set to white (default). I want the default color to be Black. I know I can do this programatically but I am trying to avoid that unless I really really need to.
There's no easy way to do exactly what you want. But what you can do is create a label with the properties you want, store it somewhere on the drawing board but not in the view, then duplicate it each time you want a new label instead of dragging on a new one. You can duplicate easily using option+drag.
I think the short answer is "no, there's not an easy way to do what you're describing."
The easiest way I can think of would be to create all your UILabels (with the default setting of white text), then control-click them all and set their text color all at once – all the other ways are less convenient, or would essentially require that Apple open-source Xcode or UIKit so that we can get at their internals.
Yes, there is a way. You could loop the subviews of the target view such as:
UIView * targetView;
[...]
for(id subView in targetView.subViews){
if([subView isKindOfClass:[UILabel class]]){
[subView setBackgroundColor:clearColor];
}
}
why do the labels have to come from the object library? You could get the functionality that you want by dragging only one UILable from the library to your view set all the properties to the defaults that you want and hit copy(command+c) once. Now you can paste(command+v) your UILabel with the special property values as many times as you want, IBActions and outlets will also be retained in the copys.
If you plan to tweak more involved properties than font color and size, then I would suggest a more custom approach that will require only minimul coding before you do the bulk drag and drop work in IB.
Subclass a UILable in Xcode, set all of your properties just once in a simple return method and than call this method from both "init" and "awakeFromNib" Now go back to IB and do all your drag/dropping making sure that the labels are of your subclass.
However, it is my opinion that if you are doing this a lot, especially if you will be doing something similar again in the future, you will save a substantial amount of time and energy to implement this "label factory" in code. Its likely less code than you are imagining it will be and the kicker is that you can reuse it in the next app. anyway thats my 2cents, Good Luck

Resources