Replace the deprecation sizeWithFont:minFontSIze:actualFontSize in ios 7 - iphone

In iOS 6 i was using this method:
[self.handText sizeWithFont:font
minFontSize:10.0f
actualFontSize:&maxFontSize
forWidth:handWidth/2
lineBreakMode:UILineBreakModeClip];
xcode 5 says that 'sizeWithFont:minFontSIze:actualFontSize:forWidth:lineBreakMode:' is deprecated:first deprecated in iOS 7
Now i implemented like this:
[self.handText sizeWithAttributes:#{NSFontAttributeName:font}
minFontSize:10.0f
actualFontSize:&maxFontSize
forWidth:handWidth/2
lineBreakMode:NSLineBreakByClipping];
here xcode throws another warning saying:
'Instance method -sizeWithAttributed:minFontSize:forWidth:lineBreakMode:'not found(return type defaults to 'id')
Can anyone please help me to fix this warning.

Use this helper method instead:
-(CGSize)frameForText:(NSString*)text sizeWithFont:(UIFont*)font constrainedToSize:(CGSize)size lineBreakMode:(NSLineBreakMode)lineBreakMode {
NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = lineBreakMode;
NSDictionary * attributes = #{NSFontAttributeName:font,
NSParagraphStyleAttributeName:paragraphStyle
};
CGRect textRect = [text boundingRectWithSize:size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
//Contains both width & height ... Needed: The height
return textRect.size;
}
Use like so, if you need to support both iOS 6 and iOS 7:
#ifdef __IPHONE_7_0
titleSize = [self frameForText:self.titleLabel.text sizeWithFont:self.titleLabel.font constrainedToSize:CGSizeMake(labelMaxWidth,self.titleLabel.font.lineHeight) lineBreakMode:self.titleLabel.lineBreakMode ];
subtitleSize = [self frameForText:self.subtitleLabel.text sizeWithFont:self.subtitleLabel.font constrainedToSize:CGSizeMake(labelMaxWidth,self.subtitleLabel.font.lineHeight) lineBreakMode:self.subtitleLabel.lineBreakMode];
#else
titleSize = [self.titleLabel.text sizeWithFont:self.titleLabel.font
constrainedToSize:CGSizeMake(labelMaxWidth,self.titleLabel.font.lineHeight)
lineBreakMode:self.titleLabel.lineBreakMode];
subtitleSize = [self.subtitleLabel.text sizeWithFont:self.subtitleLabel.font
constrainedToSize:CGSizeMake(labelMaxWidth,self.subtitleLabel.font.lineHeight)
lineBreakMode:self.subtitleLabel.lineBreakMode];
#endif

The method signature is:
- (CGSize)sizeWithAttributes:(NSDictionary *)attrs
which means you cannot specify any more argument than the first one (array of attributes). So, you are basically using a method (sizeWithAttributed:minFontSize:forWidth:lineBreakMode:) which is not existing in the iOS SDK.
For a workaround, please have a look at this question.

you can use this method
- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(7_0);

Related

Custom CallOut not displayed correctly in ios6?

As i want to implement the custom call out in the mkmapview i am using these classes CalloutMapAnnotationView.h and CalloutMapAnnotationView.m
I have extracted these classes from the following links
https://github.com/asalom/Custom-Map-Annotation-Callouts/blob/master/Classes/CalloutMapAnnotationView.h
https://github.com/asalom/Custom-Map-Annotation-Callouts/blob/master/Classes/CalloutMapAnnotationView.m
These work fine in ios5 but in ios6 when i am clicking on the call out the map view is moving and call out is not showing correctly as shown in the below figures while i was zooming also its not coming correctly i have tried several ways to get rid out of this problem by checking the version of os and tried to change the some of the methods in the classes but of not use.
After implementing these in ios5 map view coming like this
In Ios6 This one not coming properly as like in ios5. for example
I too have faced the same problem in iOS 6 using these classes. These changes worked for me:
1) Change in this method:
This method you will implement in your map view class
(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView*)view
as following order of lines
self.selectedAnnotationView = view;
[self.mapView addAnnotation:self.calloutAnnotation];
2) In CalloutMapAnnotationView.m file
- (void)adjustMapRegionIfNeeded in this method first 5 lines like bellow
CGFloat xPixelShift = 0;
if ([self relativeParentXPosition] < 38) {
xPixelShift = 38 - [self relativeParentXPosition];
} else if ([self relativeParentXPosition] > self.frame.size.width - 38) {
xPixelShift = (self.frame.size.width - 38) - [self relativeParentXPosition];
}
3) In same class CalloutMapAnnotationView.m - (void)drawRect:(CGRect)rect in this method afterCGFloat parentX = [self relativeParentXPosition];
line and above rect = self.bounds; this line
add following lines
if ([self relativeParentXPosition] < 38) {
parentX = 38;
} else if ([self relativeParentXPosition] > self.mapView.frame.size.width - 38) {
parentX = [self relativeParentXPosition]-25;
}
4) In same class CalloutMapAnnotationView.m.
- (void)didMoveToSuperview {
[super didMoveToSuperview];
[self.superview bringSubviewToFront:self];
}
You can use directly the above classes and use them they work fine in both iOS 5 & iOS 6.
You should make necessary changes according to your requirements.
just u can add nsstring title and nstring subtitle like that and
_name is what title u want .
- (NSString *)title {
return _name;
}
- (NSString *)subtitle {
return [NSString stringWithFormat:#"%f, %f", _coordinate.latitude, _coordinate.longitude];
}

UILabel justify left and right

i have UILabel (cocoa touch framework) and i want to right and left justify its text.
as a consequence it will stretch the text inside.
Example:
like if i had this text "While the saved costs of physical manufacturing and shipping" it would appear like the following:
"While the saved"
"c o s t s o f"
"p h y s i c a l"
"manufacturing"
"a n d shipping"
as you can see left and right justification...
how can i achieve that ???
many thanks
i'm sorry i had to put the double qoutations to post the question.
You should use my OHAttributedLabel class.
It has everything needed to display an NSAttributedString, including justifying left, center, right… and justified, and is really simple to use.
You can find it here on github. See the sample code provided that also shows how to change text justification.
// suppose that label is an IBOutlet to an OHAttributedLabel (subclass oh UILabel)
label.textAlignment = UITextAlignmentJustify; // and that's all, OHAttributedLabel does everything needed for you!
(Note: UITextAlignmentJustify is a constant defined in OHAttributedLabel headers that matches corresponding CoreText constant for justify alignment. This constant does not exists in Apple's SDK)
[EDIT] iOS6 SDK
Since iOS6 SDK, the UITextAlignmentJustify does not work anymore and generate a crash at runtime. Now you should set the text alignment of your NSAttributedString itself instead of using the textAlignment property of the label.
Using UIWebView can be slow, so if that's an issue CoreText is the way to go.
Here's some code that uses core text to display an attributed string on a view. It indents a bit like UILabel. I've left some other paragraph formatting options in to illustrate how you can set other paragraph properties and also set the attributed string to bold. Remember you'll need to add the CoreText framework otherwise you'll get build errors.
This code doesn't full justify the last line. Not sure you can get this for free in CoreText.
the .h file
//
// SmartLabel.h
//
#import <UIKit/UIKit.h>
#import <CoreText/CoreText.h> // needed for CTFontRef, CTFontCreateWithName
#interface SmartLabel : UIView
{
NSMutableAttributedString* _pgSmartString;
}
#property (nonatomic, retain) NSMutableAttributedString* smartString;
- (void) setText: (NSString*) string;
- (void) formatString;
#end
And the .m file
//
// SmartLabel.m
//
#import "SmartLabel.h"
#implementation SmartLabel
#synthesize smartString = _pgSmartString;
- (void)dealloc
{
[_pgSmartString release];
[super dealloc];
}
- (id)initWithFrame:(CGRect)frame;
{
if ((self = [super initWithFrame:frame]))
{
[self setBackgroundColor: [UIColor clearColor]];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
CGContextRef graphicsContext = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(graphicsContext, CGAffineTransformIdentity);
// turns things right way up
CGContextTranslateCTM(graphicsContext, 0, self.bounds.size.height);
CGContextScaleCTM(graphicsContext, 1.0, -1.0);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)[self smartString]);
CGRect bounds = [self bounds];
bounds.origin.x = bounds.origin.x + 8;
bounds.size.width = bounds.size.width - 16;
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, bounds);
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [[self smartString] length]), path, NULL);
CFRelease(path);
CTFrameDraw(frame, graphicsContext);
CFRelease(frame);
CFRelease(framesetter);
}
- (void) setText: (NSString*) string;
{
NSMutableAttributedString* attributedString = [[NSMutableAttributedString alloc] initWithString:string];
[self setSmartString:attributedString];
[attributedString release];
[self formatString];
}
- (void) formatString;
{
CTTextAlignment alignment = kCTJustifiedTextAlignment; // could put different alignments here
CGFloat paragraphSpacing = 11.0;
CGFloat paragraphSpacingBefore = 0.0;
CGFloat firstLineHeadIndent = 0.0;
CGFloat headIndent = 0.0;
CTParagraphStyleSetting altSettings[] =
{
{ kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment), &alignment},
{ kCTParagraphStyleSpecifierFirstLineHeadIndent, sizeof(CGFloat), &firstLineHeadIndent},
{ kCTParagraphStyleSpecifierHeadIndent, sizeof(CGFloat), &headIndent},
{ kCTParagraphStyleSpecifierParagraphSpacing, sizeof(CGFloat), &paragraphSpacing},
{ kCTParagraphStyleSpecifierParagraphSpacingBefore, sizeof(CGFloat), &paragraphSpacingBefore},
};
CTParagraphStyleRef style;
style = CTParagraphStyleCreate( altSettings, sizeof(altSettings) / sizeof(CTParagraphStyleSetting) );
if ( style == NULL )
{
NSLog(#"*** WARNING *** Unable To Create CTParagraphStyle in apply paragraph formatting" );
return;
}
[[self smartString] addAttributes:[NSDictionary dictionaryWithObjectsAndKeys:(NSObject*)style,(NSString*) kCTParagraphStyleAttributeName, nil] range:NSMakeRange(0,[[self smartString] length])];
CFRelease(style);
UIFont* boldFont = [UIFont boldSystemFontOfSize:12.0];
CTFontRef boldCoreTextFontReference = CTFontCreateWithName ((CFStringRef)[boldFont fontName],[boldFont pointSize], NULL);
[[self smartString] addAttributes:[NSDictionary dictionaryWithObjectsAndKeys:(NSObject*)boldCoreTextFontReference,(NSString*) kCTFontAttributeName, nil] range:NSMakeRange(0,[[self smartString] length])];
}
#end
And to put to use, something like this:
SmartLabel* smartLabel = [[SmartLabel alloc] initWithFrame:CGRectMake(20, 120, 90, 140.0)];
[[self window] addSubview:smartLabel];
[smartLabel setText:#"While the saved costs of physical manufacturing and shipping"];
[smartLabel release];
Its very easy after the release of IOS 6.
Use this
//build a style for justification
NSMutableParagraphStyle *stringStyle=[[NSMutableParagraphStyle alloc]init];
[stringStyle setAlignment:NSTextAlignmentJustified];
//build a string with the particular paragraph style
NSMutableAttributedString* yourString=[[NSMutableAttributedString alloc]init];
[yourString addAttribute:NSParagraphStyleAttributeName value:stringStyle range:NSMakeRange(0, [yourString length])];
//and here you go
UILabel *yourLabel;
yourlabel.attributedText=yourString;
From iOS 6 you can use NSMutableAttributedString for this,
NSMutableAttributedString* attrStr = [[NSMutableAttributedString alloc] initWithData:[#"Your String value" dataUsingEncoding:NSUTF8StringEncoding] options:#{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:nil];
NSRange rangeOfTitle = NSMakeRange(0,[attrStr length]);
[attrStr addAttribute: NSFontAttributeName value:[UIFont fontWithName:#"Calibri" size:19.0]range:rangeOfTitle];
myLabel.attributedText = attrStr;
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setLineSpacing:10];
style.lineBreakMode = NSLineBreakByWordWrapping;
style.alignment = NSTextAlignmentJustified;
[attrStr addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, myLabel.text.length)];
myLabel.attributedText = attrStr;
The perfect solution is to used NSMutableParagraphStyle
NSMutableParagraphStyle *paragraphStyles = [[NSMutableParagraphStyle alloc] init];
paragraphStyles.alignment = NSTextAlignmentJustified; //justified text
paragraphStyles.firstLineHeadIndent = 1.0;
NSDictionary *attributes = #{NSParagraphStyleAttributeName: paragraphStyles};
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString: YourString attributes: attributes];
YourLabel.attributedText = attributedString;
This is so called "full justification", but isn't supported by the UILabel system (which only has "alignments" - left, right and centre). If you want this, you'll have to code it up yourself, building a control with CoreText or similar.
Agree that this can only be done with a good bit of custom coding; which I would think will be some pretty heavy stuff. Before you get into that; and this is depending on your requirement; do consider having a UIWebView where I imagine you would be able to manage text styles and alignments with a bit more freedom using some HTML and CSS coding.
The following works as a quick fix, but note that for anything more than black plain text you'll need some styling or css.
(From: Justified Alignment in UITextView - iPhone)
I have come to a solution that works. First of all, you will need to change your UITextView and use a UIWebView instead.
Details.h
#interface Details : UIViewController {
IBOutlet UIWebView *descripcion;
}
#property (nonatomic, retain) UITextView *descripcion;
Then, load your UIWebView as follows:
Details.m
[descripcion loadHTMLString:[NSString stringWithFormat:#"<div align='justify'>%#<div>",YOUR_TEXT] baseURL:nil];

iPhone SDK 3.2 and UIAppFonts

I've added my custom font to UIAppFonts and it's loaded just fine: (shows up in [UIFont familyNames] ). When I manually set the font in viewDidLoad { [myLabel setFont: [UIFont fontWithName:#"CustomFont" size: 65.0]]; } everything works and the font is rendered.
However doing the same thing in IB doesn't (some other default font is used instead). Having to create IBOutlets for each label and fixing up the fonts manually in viewDidLoad is pretty painful.
Anyone else had problems getting the custom font support to work with 3.2 SDK and IB?
Opened a bug report with Apple and turns out it really is a bug. The workaround I ended up using is this:
// LabelQuake.h
#interface LabelQuake : UILabel
#end
// LabelQuake.m
#implementation LabelQuake
- (id)initWithCoder:(NSCoder *)decoder {
if (self = [super initWithCoder: decoder]) {
[self setFont: [UIFont fontWithName: #"Quake" size: self.font.pointSize]];
}
return self;
}
#end
Wrote a bit longer post at our blog.
had simillar kind of problem.and fixed it in this way...
add my custom font to my Resource group. then load all the fonts by the code given bellow:
- (NSUInteger) loadFonts{
NSUInteger newFontCount = 0;
NSBundle *frameworkBundle = [NSBundle bundleWithIdentifier:#"com.apple.GraphicsServices"];
const char *frameworkPath = [[frameworkBundle executablePath] UTF8String];
if (frameworkPath) {
void *graphicsServices = dlopen(frameworkPath, RTLD_NOLOAD | RTLD_LAZY);
if (graphicsServices) {
BOOL (*GSFontAddFromFile)(const char *) = dlsym(graphicsServices, "GSFontAddFromFile");
if (GSFontAddFromFile)
for (NSString *fontFile in [[NSBundle mainBundle] pathsForResourcesOfType:#"ttf" inDirectory:nil])
newFontCount += GSFontAddFromFile([fontFile UTF8String]);
}
}
return newFontCount;}
- (id)initWithCoder:(NSCoder *)decoder {
//load the fonts
[self loadFonts];
if (self = [super initWithCoder: decoder]) {
[self setFont: [UIFont fontWithName: #"Quake" size: self.font.pointSize]];
}
return self;
}
Hope it will work.
If you don't want to have to subclass, this solution worked quick and dirty for me. Of course it assumes that all labels have the same font, and in my case that was the case.
for (UIView *v in view.subviews) {
if ([v isKindOfClass:[UILabel class]]) {
UILabel *label = (UILabel*)v;
[label setFont:[UIFont fontWithName:#"Quake" size:label.font.pointSize]];
}
}
I put this in a helper class and just called it, passing in my current view.

Can we set the dropdown list for the textfield to select an option in iphone sdk?

I need a textfield which has an dropdown list to select an option from that.Is there any possible chances to do that in Iphone sdk?
Guys I need a quick help from ur side.
Anyone's help will be much appreciated.
Thank you,
Monish.
You use a UIPickerView instead of a dropdown list.
Edit: i missed the text field part. You are emulating a combo box.
You can use a picker + text field, and fill the text field from the pickerView:didSelectRow:inComponent delegat method
Edit2: There are some S/O questions about this already - related to UIPickerView bugs
-(void)textFieldDidBeginEditing:(UITextField *)textField{
[self gotodropdown];
}
-(void)dropdown
{
if(dropDownView==nil && ([copyListOfItems count] > 0))
{
dropDownView = [[DropDownView alloc] initWithArrayData:copyListOfItems heightTableView:200 paddingTop:0 paddingLeft:0 paddingRight:0 refView:textField animation:BOTH openAnimationDuration:2 closeAnimationDuration:0.5 ];
dropDownView.delegate = self;
[dropDownView openAnimation];
[self addSubview:dropDownView.view];
}
}
//dropdown.m
- (id)initWithArrayData:(NSMutableArray *)data heightTableView:(CGFloat)tHeightTableView paddingTop:(CGFloat)tPaddingTop paddingLeft:(CGFloat)tPaddingLeft paddingRight:(CGFloat)tPaddingRight refView:(UIView*)rView animation:(AnimationType)tAnimation openAnimationDuration:(CGFloat)openDuration closeAnimationDuration:(CGFloat)closeDuration {
if ((self = [super init])) {
//array=[[NSMutableArray alloc]init];
//[array addObjectsFromArray:data];
self.array = [data retain];
NSLog(#"ARRAYIS:%#",data);
self.refView = rView;
self.paddingTop = tPaddingTop;
self.paddingLeft = tPaddingLeft;
self.paddingRight = tPaddingRight;
self.heightTableView = tHeightTableView;
self.open = openDuration;
self.close = closeDuration;
CGRect refFrame = refView.frame;
self.view.frame = CGRectMake(refFrame.origin.x-paddingLeft,refFrame.origin.y+refFrame.size.height+paddingTop,refFrame.size.width+paddingRight, heightTableView);
self.view.layer.shadowColor = [[UIColor blackColor] CGColor];
self.view.layer.shadowOffset = CGSizeMake(5.0f, 5.0f);
self.view.layer.shadowOpacity =1.0f;
self.view.layer.shadowRadius = 5.0f;
animationType = tAnimation;
}
return self;
}
use tableview delegate for further details

Stop UITextView from jumping when programmatically setting text

I have to update a small amount of text in a scrolling UITextView. I'll only be inserting a character where the cursor currently is, and I'll be doing this on a press of a button on my navigation bar.
My problem is that whenever I call the setText method of the text view, it jumps to the bottom of the text. I've tried using contentOffset and resetting the selectedRange but it doesn't work! Here's my example:
// Remember offset and selection
CGPoint contentOffset = [entryTextView contentOffset];
NSRange selectedRange = [entryTextView selectedRange];
// Update text
entryTextView.text = entryTextView.text;
// Try and reset offset and selection
[entryTextView setContentOffset:contentOffset animated:NO];
[entryTextView setSelectedRange: selectedRange];
Is there any way you can update the text without any scroll movement at all... as if they'd just typed something on the keyboard?
Edit:
I've tried using the textViewDidChange: delegate method but it's still not scrolling up to the original location.
- (void)textViewDidChange:(UITextView *)textView {
if (self.programChanged) {
[textView setSelectedRange:self.selectedRange];
[textView setContentOffset:self.contentOffset animated:NO];
self.programChanged = NO;
}
}
- (void)changeButtonPressed:(id)sender {
// Remember position
self.programChanged = YES;
self.contentOffset = [entryTextView contentOffset];
self.selectedRange = [entryTextView selectedRange];
// Update text
entryTextView.text = entryTextView.text;
}
If you use iPhone 3.0 or later, you can solve this problem:
textView.scrollEnabled = NO;
//You should know where the cursor will be(if you update your text by appending/inserting/deleting you can know the selected range) so keep it in a NSRange variable.
Then update text:
textView.text = yourText;
textView.scrollEnabled = YES;
textView.selectedRange = range;//you keep before
It should work now (no more jumping)
Regards
Meir Assayag
Building on Meir's suggestion, here's code that removes the selection programmatically (yes I know there's a selection menu button that does it too, but I'm doing something a bit funky) without scrolling the text view.
NSRange selectedRange = textView.selectedRange;
textView.scrollEnabled = NO;
// I'm deleting text. Replace this line with whatever insertions/changes you want
textView.text = [textView.text
stringByReplacingCharactersInRange:selectedRange withString:#""];
selectedRange.length = 0;
// If you're inserting text, you might want to increment selectedRange.location to be
// after the text you inserted
textView.selectedRange = selectedRange;
textView.scrollEnabled = YES;
This decision works for iOS 8:
let offset = textView.contentOffset
textView.text = newText
textView.layoutIfNeeded()
textView.setContentOffset(offset, animated: false)
It is necessary to call exactly setContentOffset:animated: because only this will cancel animation. textView.contentOffset = offset will not cancel the animation and will not help.
The following two solutions don't work for me on iOS 8.0.
textView.scrollEnabled = NO;
[textView.setText: text];
textView.scrollEnabled = YES;
and
CGPoint offset = textView.contentOffset;
[textView.setText: text];
[textView setContentOffset:offset];
I setup a delegate to the textview to monitor the scroll event, and noticed that after my operation to restore the offset, the offset is reset to 0 again. So I instead use the main operation queue to make sure my restore operation happens after the "reset to 0" option.
Here's my solution that works for iOS 8.0.
CGPoint offset = self.textView.contentOffset;
self.textView.attributedText = replace;
[[NSOperationQueue mainQueue] addOperationWithBlock: ^{
[self.textView setContentOffset: offset];
}];
No of the suggested solutions worked for me. -setContentOffset:animated: gets triggered by -setText: 3 times with animated YES and a contentOffset of the end (minus the default 8pt margin of a UITextView). I wrapped the -setText: in a guard:
textView.contentOffsetAnimatedCallsDisabled = YES;
textView.text = text;
textView.contentOffsetAnimatedCallsDisabled = NO;
In a UITextView subclass in -setContentOffset:animated: put
if (contentOffsetAnimatedCallsDisabled) return; // early return
among your other logic. Don’t forget the super call. This works.
Raphael
In order to edit the text of a UITextView, you need to update it's textStorage field:
[_textView.textStorage beginEditing];
NSRange replace = NSMakeRange(10, 2); //enter your editing range
[_textView.textStorage replaceCharactersInRange:replace withString:#"ha ha$ "];
//if you want to edit the attributes
NSRange attributeRange = NSMakeRange(10, 5); //enter your editing attribute range
[_textView.textStorage addAttribute:NSBackgroundColorAttributeName value:[UIColor greenColor] range:attributeRange];
[_textView.textStorage endEditing];
Good luck
in iOS 7. There seams to be a bug with sizeThatFits and having linebreaks in your UITextView the solution I found that works is to wrap it by disabling scrolling. Like this:
textView.scrollEnabled = NO;
CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
textView.scrollEnabled = YES;
and weird jumping has been fixed.
I hit a a similar, if not the same, problem in IOS9. Changing the characteristics of some text to, say, BOLD caused the view to scroll the selection out of sight. I sorted this by adding a call to scrollRangeToVisible after the setSelectedRange:
[self setSelectedRange:range];
[self scrollRangeToVisible:range];
Take a look at the UITextViewDelegate, I believe the textViewDidChangeSelection method may allow you to do what you need.
Old question but I had the same issue with iOS 7 app. Requires changing the contentOffset a little bit after the run loop. Here is a quick idea.
self.clueString = [self.level clueText];
CGPoint point = self.clueText.contentOffset;
self.clueText.attributedText = self.clueString;
double delayInSeconds = 0.001; // after the run loop update
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.clueText setContentOffset:point animated:NO];
});
Finally try this, checked on iOS 10
let offset = textView.contentOffset
textView.attributedText = newValue
OperationQueue.main.addOperation {
self.textView.setContentOffset(offset, animated: false)
}
Not so elegant solution- but it works so who cares:
- (IBAction)changeTextProgrammaticaly{
myTextView.text = #"Some text";
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(rewindOffset) userInfo:nil repeats:NO];
}
- (void)rewindOffset{
[myTextView setContentOffset:CGPointMake(0,0) animated: NO];
}
I found a solution that works reliably in iOS 6 and 7 (and probably earlier versions). In a subclass of UITextView, do the following:
#interface MyTextView ()
#property (nonatomic) BOOL needToResetScrollPosition;
#end
#implementation MyTextView
- (void)setText:(NSString *)text
{
[super setText:text];
self.needToResetScrollPosition = YES;
}
- (void)layoutSubviews
{
[super layoutSubviews];
if (self.needToResetScrollPosition) {
self.contentOffset = CGPointMake(0, 0);
self.needToResetScrollPosition = NO;
}
}
None of the other answers work in iOS 7 because it will adjust the scroll offsets at display time.