I want my app to be when you click the stepper it will resize the font in a UITextView. The problem is I'm getting errors.
- (IBAction)myStepper:(id)sender {
[myStepper setMinimumValue:14.0]
self.myStepper.maximumValue =20.0;
UIFont newSize = [myTextView fontWithSize:self.stepper.value];
self.myTextView.font = newSize;
}
This all of my code, am I missing something?
You are missing a self and a semicolon in the first line:
[self.myStepper setMinimumValue:14.0];
And an asterisk and self in this line, and stepper should be myStepper:
UIFont *newSize = [self.myTextView fontWithSize:self.myStepper.value];
I would clean your method a bit like this:
- (IBAction)myStepperValueChanged:(UIStepper *)sender {
[sender setMinimumValue:14.0];
[sender setMaximumValue:20.0];
UIFont * newSize = [UIFont fontWithName:myTextView.font.fontName size:sender.value];
[self.myTextView setFont:newSize];
}
but I'd put the first two lines into the -viewDidLoad method as part of the standard init procedure, if they are static values in runtime using the outlet's name (I assume it is myStepper in your class):
[myStepper setMinimumValue:14.0];
[myStepper setMaximumValue:20.0];
or I'd set these values in the Interface Builder, and you'd not need to deal with any outlet for your stepper at all.
NOTE: it is hard to tell which solution would fit better for you, you have not shared too much information which could help me to recommend a specific solution.
For easier code-reading, you shouldn't give your action method the same name of your UISteppert property. Change it to -(IBAction)stepperValueChanged:(id)sender for example.
You don't need to set the min and max value in this method, but in your initialization methods
- (void) viewDidLoad
{
[super viewDidLoad];
// Various implementation
self.myStepper.minimumValue = 14;
self.myStepper.maximumValue = 20.0;
}
- (IBAction) stepperValueChanged:(id)sender
{
self.myTextView.font = [UIFont fontWithSize:self.myStepper.value];
}
It looks like you are some issues understanting the differences between method and properties, you should read some documentation and tutorials if you're beginning development (and welcome to the development world ;) ).
EDIT :
The property myStepper doesn't exists in your class. If you use interface builder, you have to link your stepper to an UIStepper property : this apple tutorial will help you : https://developer.apple.com/library/ios/recipes/xcode_help-interface_builder/articles-connections_bindings/CreatingOutlet.html .
Otherwise, if you don't use Interface Builder, you must add an UIStepper property to your class and allocate it by yourself.
Related
I am trying to retroactively localize an app by subclassing an IBDesignable to have a property like so:
#property IBInspectable NSString *localizedKey;
Then I thought I could easily override the proper function in the UILabel's lifecycle to do this:
if (self.localizedKey) self.text = NSLocalizedString(self.localizedKey, nil);
Here's an example of what I tried to do:
- (void) drawRect:(CGRect)rect {
NSLog(#"roundedlabel");
[super drawRect:rect];
[self.layer setCornerRadius:cornerRadius];
[self.layer setMasksToBounds:YES];
[self.layer setBorderWidth:borderWidth];
[self.layer setBorderColor:[borderColor CGColor]];
self.clipsToBounds = YES;
}
- (void) willMoveToSuperview:(UIView *)newSuperview {
[super willMoveToSuperview:newSuperview];
NSLog(#"roundedlabel");
if (self.localizedKey) self.text = NSLocalizedString(self.localizedKey, nil);
}
I also tried moving the if (self.localizedKey) to various locations in drawRect.
My plan was to then set up the Localizable.strings file manually with known localizedKeys assigned working through the XIB files. However, I am finding two things.
It seems as though the normal methods called in the life cycle
of a view are not being called for my IBDesignable UILabel subclass.
I have entered log statements into drawRect and
willMoveToSuperview, and these log statements never print out.
XCode almost always crashes & immediately closes when I try to open
a xib in Interface Builder that contains this subclassed label (so no error messages).
At run time, when I see a view that involves an affected xib, I don't see any sign of the localized string AND I don't see 'roundedlabel' printed anywhere in my log.
What's going on? In particular:
(1) How come these functions don't run at all for my subclassed IBDesignable UILabel subclass?
(2) Is there a way to do what I want to do?
I'd create an extension on UILabel and use runtime key values in the storyboard / XIB to set the localisation keys.
extension UILabel {
func setHBLocalisationKey(key: String) {
self.text = ...
}
}
or
#implementation UILabel (HBLocalisation)
- (void)setHBLocalisationKey:(NSString *)key {
self.text = NSLocalizedString(key, nil);
}
#end
This will now work on any label without requiring a custom subclass and it won't tamper with the Xcode UI which seems to be causing some issues with your current approach.
I am trying to have dynamic font size for the textview.I have mad a custom class for the dynamic font size of text view.I have used following code for the custom class.
#import "CustomTextView.h"
#implementation CustomTextView
- (void)drawRect:(CGRect)rect
{
// Drawing code
int numLines = self.contentSize.height / self.font.lineHeight;
self.font = [UIFont fontWithName:self.font.fontName size:((self.frame.size.height / numLines) - 4)];
[super drawRect: rect];
}
#end
but this does not work.it shows a black color for the textview.please guide how to do it?
There must be something wrong while implementing "CustomTextView.h" in your ViewController.
Let us know how u have done the same.
Share your code in ViewController.
Have you added "CustomTextView" as subview in your view controller.
So in my code, I was checking if my characters fit in my Label or not and had the following line :
return self.adjustsLetterSpacingToFitWidth;
This was placed in an implementation of UILabel. Can someone tell me just what is the exact alternative for this? The documentation says - Use NSKernAttributeName, but I wasn't quite able to understand that. Can someone help me on this?
In the larger sense - The method is called as:
xLab.adjustLetterSpacingToFitWidth = YES;
In my code, I have:
#implementation UILabel ()
- (BOOL) getter {
return self.adjustsLetterSpacingToFitWidth;
}
- (void) setter:(BOOL) setVal {
self.adjustsLetterSpacingToFitWidth = setVal;
}
#end
First of all, your getter and setter are entirely superfluous as shown; wherever you call getter and/or setter, you could simply get/set adjustsLetterSpacingToFitWidth directly.
As for the question of how to do auto-kerning with NSKernAttributeName, Apple's documentation says: “To turn on auto-kerning in the label, set NSKernAttributeName of the string to [NSNull null]”, i.e., you would do something like:
NSMutableAttributedString *s;
s = [[NSMutableAttributedString alloc] initWithString:my_uilabel.text];
[s addAttribute:NSKernAttributeName
value:[NSNull null]
range:NSMakeRange(0, s.length)];
my_uilabel.attributedText = s;
But if you did not want to do automatic adjustment of letter spacing but rather find out whether the text fits in the label or not, you might want to check the various methods in NSString UIKit additions. (This guess of intent is based on the wording in the original question.)
I am using a stepper to control the font size of a text view, but there is no action being fired until I press the stepper twice. Why is this happening?
The following code is for the `mystepper' IBAction:
- (IBAction) changeFontSize:(id)sender
{
[myStepper setMinimumValue:14.0]
self.myStepper.maximumValue =20.0;
UIFont newSize = [myTextView fontWithSize:self.stepper.value];
self.myTextView.font = newSize;
}
I find the problem is that i need set the current value of stepper equals to minimumvalue. However, I want the value of size can pass through in muiltple scences so that the fontSize doesn't need to be press overtime. How can i get it???
In viewDidLoad:
[myStepper setMinimumValue:14.0]
[myStepper setMaximumValue:20.0]
UIFont newSize = [myTextView fontWithSize:self.stepper.value]; // provide some default value to myStepper
self.myTextView.font = newSize;
// assign one method to stepper - value changed event
- (IBAction)stepperValueChanged:(id)sender
{
double stepperValue = ourStepper.value;
[self.myTextView setFont:[self.myTextView.font fontWithSize:stepperValue]];
}
This is the core logic, but there might be minor changes reuqire, to satisfy your requirement.
Hope this will help you.
As you want to set the size in multiple screens. So one practice would be to use userDefaults.
In your viewDidLoad method you need to read the userDefaults and check if there is no saved data for the same, save minValue and maxValue.
And in your method
- (IBAction)stepperValueChanged:(id)sender{
double stepperValue = ourStepper.value;
...
}
use the new value and update the userDefaults value.
And fetch the userDefaults value and use that size throughout the application.
I am writing a fairly simple application which spawns a thread which ultimately calls the following method to put a UILabel at a certain location. I had expected ARC to clean up the labels as the method closed. I was wrong. :)
Is there a way to force these to be cleaned up or is there something obvious that I am missing? Thanks!
-(void) drawNumberLabel:(NSString *)labelText xloc:(float)xLocation yLoc:(float)yLocation {
UILabel *tempLabel;
tempLabel = [[UILabel alloc] initWithFrame:CGRectMake(xLocation, yLocation, 27.0, 59.0)];
tempLabel.font = [UIFont fontWithName:#"Helvetica" size:fontSize];
tempLabel.text = labelText;
tempLabel.backgroundColor = backgroundColor;
tempLabel.textColor = textColor;
[self addSubview:tempLabel];
}
What do you mean by "clean up the labels"? Are you expecting that tempLabel would be deallocated at the end of this method? It won't, because when you call [self addSubview:tempLabel], your view retains the label. When the superview is deallocated, the labels you've added will also be deallocated.
When you are using ARC (Automatic Reference Counting), you should never make any memory management calls because the compiler will insert these statements for you at compile-time.
The compiler should be injecting [tempLabel release]; to the end of your method at compile-time.
However, because you have added the label as a subview to a view, the containing view will retain the label, and the label will not be released until you remove the label from that view.