UITextView - setting font not working with iOS 6 on XCode 5 - ios

I'm using storyboards for my UI. I was previously using XCode 4.6 and released on iOS 6. I have since updated to iOS 7 using XCode 5 and updated the Storyboard to work nicely with XCode 5. I have one issue though:
UITextView doesn't want to display font changes within code. Text colour changes work fine. Any other property changes are fine. Font, not at all. I was using a custom font, so I checked different fonts with different sizes (i.e. systemFontOfSize:) but that didn't work. The text view only shows the font that's set in the Storyboard. What could I be missing here? Are there any auto-layout constraints that mess with this sort of thing? I had a few issues with constraints during the migration, but as I said, the fonts work fine in iOS 7.
I guess it's something in the Storyboard that I'm missing, as if I create a UIViewController and add a text view in code, it works fine.
I'd put up some code, but I'm not sure it'd help at all in this case.

Even stranger, this only happens on iPhone, not iPad.
If you're setting the font in code and don't want an editable text view, do this:
textView.editable = YES;
textView.font = newFont;
textView.editable = NO;

In my case, it is matter of 'selectable' property of UITextView.
So I checked 'selectable' property of UITextView in Storyboard Editor to set it YES
and later in viewWillAppear set this property to NO.
textview.text = #"some text";
textview.selectable = NO;

The issue was caused by the editable property being false in the Storyboard. I have absolutely no idea why this caused the font to remain unchanged - and only on iOS 6.

For me it's work if you set the text of your UITextView and after set the font (same for color) :
_myTextView.text = #"text";
[_myTextView setFont:[UIFont fontWithName:#"Helvetica Neue" size:18.0f]];
_myTextView.textColor = [UIColor whiteColor];

Thank you for all the answers guys. Issue is still present on iOS9. What i've found out, is that when you set "User Interaction Enabled = false" in the Interface Builder you can leave Editable and Selectable = true and user will not be able to edit a text view.
So, my solution is:
Set User Interaction Enabled = False in IB
Set Editable = True in IB
Set Selectable = True in IB
Configure your text view in whatever way you want.

Code for swift:
textOutlet.editable = true
textOutlet.textColor = UIColor.whiteColor()
textOutlet.font = UIFont(name: "ArialMT", size: 20)
textOutlet.editable = false
Or if you change the text first it magically gets solved
textOutlet.text = "omg lol wtf"
textOutlet.textColor = UIColor.whiteColor()
textOutlet.font = UIFont(name: "ArialMT", size: 20)

I found the font size was being ignored. This was resolved by ticking the checkbox called: Selectable (having selected the UITextView within the storyboard)

This issue only happens when setting Selectable property to FALSE in the Interface Builder.
In case you are required to have the Editable and Selectable properties set to FALSE do it from the CODE and not in the Interface Builder.
Summing up, make Editable and Selectable properties = YES in the Interface Builder and then add the following code in case you need the properties to be FALSE:
_textView.editable = NO;
_textView.selectable = NO;
Hope this helps,

Swift 3 category that worked for me:
extension UITextView {
func setFontAndUpdate(_ font: UIFont?) {
self.font = font
// Font doesn't update without text change
let text = self.text
self.text = nil
self.text = text
}
}

In my case(Developing on Xcode 7.3, iOS 9),
The cause was the order of setting text and font-family/size, not the options of editable or selectable many answers tell there.(and I don't get any storyboard, xib on that Textview.)
If I input like
[myTextView setFont:[UIFont fontWithName:#"HelveticaNeue-Italic" size:20]];
myTextView.attributedText = mAttStr;
then the font's family and size are not changed, but else
when I reverse those two step, it works. Setting text should be ahead of setting font's family/size.

As mentioned by others:
textView.font = UIFont.systemFont(ofSize: 16)
textView.isEditable = false
p.s. no need to first set isEditable as true since it's true by default: a little shorter, a little nicer

In my case, I solved by setting the new font in "viewDidLayoutSubviews".

Related

UITextView link detection in iOS 7

I have a UITextView which is managed via Interface Builder. As data detection I have "Links" checked. In iOS 6 everything is working fine and links are highlighted and are clickable. In iOS 7 though, all links remain just plain text. The editable and selectable checkboxes are unchecked.
What may be of concern is that the UITextView is a subview of a container view which is again inside a UIScrollView.
It seems that in iOS 7 link detection only works if the UITextView is selectable. So making my UITextView not selectable stopped the the link detection from working.
I also tested this in iOS 6 and I can confirm that in iOS 6 the link detection works fine even with the UITextView not being selectable.
I was having some problems with phone number detection today. It seemed like the UITextView would retain old phone numbers and keep text highlighted after I had set the text to something else.
I found that if I setText:nil before setting the text to the new string, it would reset the textview, and phone numbers would highlight as normal. I'm wondering if this is some kind of bug with UITextView in iOS 7.0
Either way, this did work for me.
When iOS7 first came out this plagued me and I found an answer in this thread (setting the text attribute of the UITextView to nil before setting the actual value did the trick). Then suddenly, the problem (for me it was the entire string being highlighted as a link) cropped back up (assumedly due to an iOS update).
What finally did the trick for me was to stop using the text attribute and set the attributedText. Once I did this, the need for setting fonts/scrolling/selectable/editable/etc. programmatically, disappeared. I defined my UITextView in IB, set the values as I wanted (not scrollable, not editable, selectable, detecting links and phone numbers) and then built an attributed string and set:
myUITextView.attributedString = myAttributedString;
And suddenly everything worked as expected. Hope this helps someone else down the road.
I had the same issue and disabling scrolling on the UITextView activates the link detection on load rather than only working once the user has interacted with the textview. The UITextView also had to be selectable and non-editable.
detailTextView.scrollEnabled = NO;
detailTextView.editable = NO;
detailTextView.selectable = YES;
Being selectable or having scroll enabled isn't necessary on iOS6.
Another thing to check is that userinteraction is enabled on the cell and content view of the cell, otherwise the link won't be clickable.
Check These Lines must be added to use data detector property of textview in UItableView cell.
txtvwMsgText.userInteractionEnabled = YES;
txtvwMsgText.dataDetectorTypes = UIDataDetectorTypeLink;
txtvwMsgText.scrollEnabled = NO;
txtvwMsgText.editable = NO;
txtvwMsgText.selectable = YES;
You should check out NSDataDetector.
You can use this to find and deal with different data (links, phone numbers and more). Have a look on this site:
http://nshipster.com/nsdatadetector/
You can also use the dataDetectorTypes property of UITextView to set what you want to detect in code. May just be a storyboard transition problem for you.
textView.dataDetectorTypes = UIDataDetectorTypeLink;
Be aware, that your textview will only recognize the links if not editable!
Here is a nice tutorial on how to make an editable UITextView with `link detection``
Editable UITextView with link detecion
I've not experienced any problems with that solution since now.
The trick is a GestureRecognizer forwaring touches and enabling/disabling the editing.
You could apply the same thing with the selectable / not selectable issue on iOS7
After few tests, I found solution.
If you want links active and you don't want selection enabled, you need to edit gestureRecognizers.
For example - there are 3 LongPressGestureRecognizers. One for click on link (minimumPressDuration = 0.12), second for zoom in editable mode (minimumPressDuration = 0.5), third for selection (minimumPressDuration = 0.8). This solution removes LongPressGestureRecognizer for selecting and second for zooming in editing mode.
NSArray *textViewGestureRecognizers = self.captionTextView.gestureRecognizers;
NSMutableArray *mutableArrayOfGestureRecognizers = [[NSMutableArray alloc] init];
for (UIGestureRecognizer *gestureRecognizer in textViewGestureRecognizers) {
if (![gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
[mutableArrayOfGestureRecognizers addObject:gestureRecognizer];
} else {
UILongPressGestureRecognizer *longPressGestureRecognizer = (UILongPressGestureRecognizer *)gestureRecognizer;
if (longPressGestureRecognizer.minimumPressDuration < 0.3) {
[mutableArrayOfGestureRecognizers addObject:gestureRecognizer];
}
}
}
self.captionTextView.gestureRecognizers = mutableArrayOfGestureRecognizers;
Tested on iOS 9, but it should work on all versions (iOS 7, 8, 9).
I hope it helps! :)
I've found the trick, this works in iOS 7!
You have to set the UITextView selectable in your xib or programmatically
self.yourTextView.selectable = YES;
and then you have to disable scrolls and enable again after set your text.
self.yourTextView.scrollEnabled = NO;
[self.yourTextView setText:contentString];
self.yourTextView.scrollEnabled = YES;
So using a UITextView keeping it enabled, selectable, not scrollable & links detectable is not as simple as it seems. I encountered this in iOS 8. So my solution was to do something like this in viewDidLoad and then set editable property to NO when textBox editing is done(usually would be a method like doneIsTapped). The trick here is to set editable property to NO after setting text value to textview is completed. This will enable links in the UITextview.
- (void)viewDidLoad
{
[super viewDidLoad];
self.txtViewComment.editable = YES;
self.txtViewComment.selectable = YES;
self.txtViewComment.dataDetectorTypes = UIDataDetectorTypeLink;
self.txtViewComment.scrollEnabled = NO;
}
and
- (IBAction)doneIsTapped:(id)sender
{
self.txtViewComment.text = #"set text what ever you want";
self.txtViewComment.editable = NO;
}
this made the links enabled in textview. Also I would recommend not to use story board at this time(or until apple fixes this problem) and just use code to avoid any unnecessary confusion. Hope this help.
Deactivating UITextViews scrolling ability did the trick for me in a similar setup.
Changing the Tint color to other color actually works.
However if selectable enable the tint will also be the same color.
Make the scrolling property of UITextView to No. it will work...
Self.textView.ScrollingEnable = NO;
None of the above worked for me, instead I did this:
[self.textView setDataDetectorTypes:UIDataDetectorTypeNone];
[self.textView.setTextColor:[UIColor whiteColor]];
[self.textView setDataDetectorTypes:UIDataDetectorTypeNone];
I did this with my textview that was supposed to detect all types, and which had non detected color set to white. You can change the code to represent your proper color and link types to detect.
While this thread is old, I didn’t see an answer that worked for me with Swift, so here goes for Swift 2.2
textView.dataDetectorTypes = UIDataDetectorTypes.Link
textView.selectable = true
This workaround works for me:
textView.selectable = YES;
textView.delegate = self;
- (void) textViewDidChangeSelection:(UITextView *)textView;
{
NSRange range = NSMakeRange(NSNotFound, 0.0);
if ( range.length && !NSEqualRanges(range, textView.selectedRange) ) {
textView.selectedRange = range;
}
}
If you are adding UITextview programmatically just add below lines:
_textView.userInteractionEnabled = YES;
_textView.dataDetectorTypes = UIDataDetectorTypeLink;
_textView.scrollEnabled = NO;
_textView.editable = NO;
This worked for me.

UIButton with multi-line titleLabel in InterfaceBuilder

I've been wondering, is there a nice way to make UIButtons with multi-line titleLabel in Interface Builder? I've found none and puttin a separate UILabel on top of each button and tracking it's color on press and other events is not very straightforward.
Maybe there are better alternatives done in code if there's no such way in IB?
Code:
To allow multiple line you can use:
button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
button.titleLabel.textAlignment = UITextAlignmentCenter;
[button setTitle: #"Line1\nLine2" forState: UIControlStateNormal];
In iOS 6, UILineBreakModeWordWrap and UITextAlignmentCenter are deprecated, so use:
button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
Interface Builder:
In interface builder select UIButton
on the right side Utilities pane under Attributes Inspector, you'll see an option for Line Break
Choose Word Wrap
You can do solely in Interface Builder a couple ways.
First by simply setting the wrap feature. This offers limited customizability though.
For more customizability, change the "Plain Text" to "Attributed Text" and then you can do most things without any code.
In the case you are using only plain XCode 9.4:
Set Line Break to any option (to enable numberOfLines) in the Attributes inspector:
Then you can set KeyPath as
titleLabel.numberOfLines
in the Identity inspector:
Just to mention if one does not want word wrap but still want to achieve multi line title on a UIButton it can be done by setting lineBreakMode before numberOfLines,
This is because lineBreakMode seems to cancel out numberOfLines set hence we are doing it in this order.
Swift:
button.titleLabel?.lineBreakMode = NSLineBreakMode.byTruncatingTail
button.titleLabel?.numberOfLines = 2
button.setTitle(myTitle, for: UIControlState.normal)

Change Nav Bar Title Font - DIFFERENT

As you can see in the picture below, my UIViewController IS NOT a UINavigationController, it's a common UIViewController. What I did is I put a UINavigationBar using interface builder and above it I put a UIImage. The problem is that I want to change the font of this UINavigationBar. Anyone would have a clue on how to do it?
Usually, with a common UINavigationController I use the following code:
// this will appear as the title in the navigation bar
self.label = [[UILabel alloc] initWithFrame:CGRectZero];
self.label.backgroundColor = [UIColor clearColor];
self.label.font = [UIFont fontWithName:#"Copperplate" size:22];
self.label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
self.label.textAlignment = UITextAlignmentCenter;
self.label.textColor = [UIColor whiteColor]; // change this color
self.label.text = [self.navigationItem title];
self.navigationItem.titleView = label;
[label sizeToFit];
Well it should work the same way. I think you just need an IBOutlet for the UINavigationBar, or only for the UINavigationItem (the title for your UINavigationBar) and that's it.
Storyboard Solution
There's nothing wrong with the answer above but a really simple way to do this is to select the Navigation Bar in the storyboard. Then change the Title Font in the attributes inspector.
Nota Bene
This technique is also really useful when you want to change the font
across an entire set of views whenever you are using a navigation
controller. (Just change it in one place). Xcode 7.1.1 has a couple of bugs. One of those requires that you toggle the Bar Tint from the default to another color (you can always reset it to the default if needed) in order to see the font change.
Custom Fonts
The above is currently not working when selecting a custom font (as of Xcode 7.1.1).
Please see the following SO Answer for a workaround if you need a
custom font. (tldr; add an outlet to a button or label, change the
custom font on that control, set that control as the
UINavigationItem.titleView).

Making a UITextView not editable by the user

I made this UITextView and everything is perfect except the fact that when the user taps it, the keyboard opens up. How can I disable that "editing(?)" option?
Here's the code:
- (void)loadAboutStable {
UITextView *aboutStable = [[UITextView alloc] init];
[aboutStable setText:#"Please check Your network connection"];
[self addSubview:aboutStable];}
[aboutStable setUserInteractionEnabled:NO] should do it
and if you still need scrolling:
aboutStable.editable = NO;
aboutStable.editable = NO;
should work
You can do it with XIB too by UnCheck of the editable checkbox as given in below screen :
and also do it by code :
textViewObject.editable = false
Select the UITextView in the storyboard
Choose the Property Inspector and under the Behavior section uncheck "Editable"
----Xcode version 5.0
yourTextView.editable = NO;
It will make your text View not editable. It can be called from anywhere if you have made the property of you text view in .h file like this
#property (nonatomic, strong) UITextView *youTextView;
SWIFT 2.0 & XCODE 7.0 example for solution provided by #James Webster
In Main.storyboard (default), select your TextView
Go to the Attribute Inspector of the TextView
Uncheck "User Interaction Enabled"
Swift 4 version:
aboutStable.isEditable = false
In Swift 2.0 it has to be false not NO.
theClues.selectable = false
I had a problem with making my clues appear in white letters unless I checked the selectable button on the storyboard for the textview. However, leaving "Selectable" checked and adding the line above works.
to really destroy any interactivity ;)
descriptionText.isSelectable = false;
descriptionText.isEditable = false;

How to make UIButton's text alignment center? Using IB

I can't set the title of UIButton using IB as center. My title is multi line.It is giving like this one
But I want like this one
I have given space in this but I don't want to do that. As it is not aligned exactly for some cases and I know there is a property of UILabel to set the alignment but I don't want to write a code for that.. just want to set everything from IB.
Thanks
This will make exactly what you were expecting:
Objective-C:
[myButton.titleLabel setTextAlignment:UITextAlignmentCenter];
For iOS 6 or higher it's
[myButton.titleLabel setTextAlignment: NSTextAlignmentCenter];
as explained in tyler53's answer
Swift:
myButton.titleLabel?.textAlignment = NSTextAlignment.Center
Swift 4.x and above
myButton.titleLabel?.textAlignment = .center
Use the line:
myButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
This should center the content (horizontally).
And if you want to set the text inside the label to the center as well, use:
[labelOne setTextAlignment:UITextAlignmentCenter];
If you want to use IB, I've got a small example here which is linked in XCode 4 but should provide enough detail (also mind, on top of that properties screen it shows the property tab. You can find the same tabs in XCode 3.x):
Solution1
You can set the key path in the storyboard
Set the text to your multiline title e.g. hello ⌥ + ↵ multiline
You need to press ⌥ + ↵ to move text to next line.
Then add the key path
titleLabel.textAlignment as Number and value 1, 1 means NSTextAlignmentCenter
titleLabel.numberOfLines as Number and value 0, 0 means any number of lines
This will not be reflected on IB/Xcode, but will be in centre at run time (device/simulator)
If you want to see the changes on Xcode you need to do the following: (remember you can skip these steps)
Subclass the UIButton to make the button designable:
import UIKit
#IBDesignable class UIDesignableButton: UIButton {}
Assign this designable subclass to the buttons you're modifying:
Iff done right, you will see the visual update in IB when the Designables state is "Up to date" (which can take several seconds):
Solution2
If you want to write the code, then do the long process
1.Create IBOutlet for button
2.Write code in viewDidLoad
btn.titleLabel.textAlignment = .Center
btn.titleLabel.numberOfLines = 0
Solution3
In newer version of xcode (mine is xcode 6.1) we have property attributed title
Select Attributed then select the text and press centre option below
P.S. The text was not coming multiline for that I have to set the
btn.titleLabel.numberOfLines = 0
For UIButton you should use:-
[btn setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter];
For ios 8 and Swift
btn.titleLabel.textAlignment = NSTextAlignment.Center
or
btn.titleLabel.textAlignment = .Center
For those of you who are now using iOS 6 or higher, UITextAlignmentCenter has been deprecated. It is now NSTextAlignmentCenter
EXAMPLE: mylabel.textAlignment = NSTextAlignmentCenter; Works perfectly.
For swift 4, xcode 9
myButton.contentHorizontalAlignment = .center
Assuming that btn refers to a UIButton, to change a multi-line caption to be centered horizontally, you can use the following statement in iOS 6 or later:
self.btn.titleLabel.textAlignment = NSTextAlignmentCenter;
For Swift 4:
#IBAction func myButton(sender: AnyObject) {
sender.titleLabel?.textAlignment = NSTextAlignment.center
sender.setTitle("Some centered String", for:UIControlState.normal)
}
UITextAlignmentCenter is deprecated in iOS6
Instead you can use this code:
btn.titleLabel.textAlignment=NSTextAlinmentCenter;
For Swift 3.0
btn.titleLabel?.textAlignment = .center
Try Like this :
yourButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
yourButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
Actually you can do it in interface builder.
You should set Title to "Attributed" and then choose center alignment.
You can do this from storyboard.
Select your button. Set Line Break 'Word Wrap', Set your title 'Plain' to 'Attributed'.
Select 'Center alignment'. This part is important => Click ...(More) Button. And select line breaking mode to 'Character Wrap'.
UIButton will not support setTextAlignment. So You need to go with setContentHorizontalAlignment for button text alignment
For your reference
[buttonName setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter];

Resources