views:

870

answers:

2

In this question I asked for a good way to truncate a string to fit a given UITextView. Since there was no way provided by the SDK directly, I've ended up writing the recursive method below (only called by the following public method). However, this doesn't work unless I subtract a fudge factor of 15 (kFudgeFactor) from the field width when calculating the string's height. If I don't do that, the string returned is actually too long for the field, and displays in an extra line below it. Anyone any idea why, and what I should really use instead of this fudge factor?

#pragma mark Size string to fit the new view

#define kFudgeFactor 15.0
#define kMaxFieldHeight 9999.0

// recursive method called by the main API
-(NSString*) sizeStringToFit:(NSString*)aString min:(int)aMin max:(int)aMax
{
if ((aMax-aMin) <= 1)
 {
 NSString* subString = [aString substringToIndex:aMin];
 return subString;
 }

int mean = (aMin + aMax)/2; 
NSString* subString = [aString substringToIndex:mean];

CGSize tallerSize = CGSizeMake(self.frame.size.width-kFudgeFactor,kMaxFieldHeight);
CGSize stringSize = [subString sizeWithFont:self.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];

if (stringSize.height <= self.frame.size.height)
  return [self sizeStringToFit:aString min:mean max:aMax]; // too small
else 
     return [self sizeStringToFit:aString min:aMin max:mean];// too big
}

-(NSString*)sizeStringToFit:(NSString*)aString
{

CGSize tallerSize = CGSizeMake(self.frame.size.width-kFudgeFactor,kMaxFieldHeight);
CGSize stringSize = [aString sizeWithFont:self.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];

// if it fits, just return
if (stringSize.height < self.frame.size.height)
    return aString; 

// too big - call the recursive method to size it  
NSString* smallerString = [self sizeStringToFit:aString min:0 max:[aString length]];
return smallerString; 
}
A: 

This is probably because the frame of the UIView is not the same size as the content view. UITextView subclasses from UIScrollView.

drudru
+3  A: 

UIScrollView seems to use a fixed 8-pixel inset on both sides. This is independent of alignment or font size (based on testing & observation, not any explicit knowledge of the internals).

So it seems you are right to use your fudge factor, but it should probably be 16.0, not 15.0.

Frank Szczerba
Frank, I can't prove what you've said is right, but it seems so plausible after all I've tried to get to the root of this that I'm giving you the right answer.Why oh why doesn't Apple document stuff like this? Or give us the true width back in the text view's frame?
Jane Sales
I determined this by placing a text field in IB and overlapping another view until it just covered the text, then checking the positioning (using left-justified text when measuring the left margin and right-justified for the right margin). I then changed the font and font size and verified that the margins didn't change.
Frank Szczerba