In my programmatically instantiated UITextView (initialized with NSTextContainer) the .text property is always nil

5.9k views Asked by At

[UPDATED w/ SOLUTION and WORKING CODE in bottom section]

In -viewDidLoad I alloc, initWithFrame:

Add myTextView to subView

Set some basic properties (alignment, background color, text color, etc)

Set default text

The .text does not appear. myTextView appears (as indicated by background color), set breakpoint, it has a frame, memory, etc. Everything looks right. myTextView looks good, but the .text is nil. I change it, set it, update it. No matter what the .text remains nil.

I have read the documentation over and over again. No mention of anything that I am not doing. I'm at a loss. Help.

in @interface MyController ()...

Everything used to be (weak) but I turned it up to (strong) just in case. No dice.

@property (strong, nonatomic) UIScrollView *scrollView;

@property (strong, nonatomic) UIImageView *imageView;
@property (strong, nonatomic) UILabel *titleLabel;
@property (strong, nonatomic) UITextView *contentTextView;

in viewDidLoad...

- (void)viewDidLoad {

  [super viewDidLoad];

  // scroll view
  CGSize size = CGSizeMake(703, self.view.frame.size.width);
  UIScrollView *aScrollView = [[UIScrollView alloc] initWithFrame: self.view.frame];
  self.scrollView = aScrollView;
  [self.scrollView setDelegate: self];
  [self.scrollView setDirectionalLockEnabled: YES];
  [self.scrollView setContentSize: size];
  [self.view addSubview: self.scrollView];

  // image view
  CGRect frame = CGRectMake(0, 0, 703, 400);
  UIImageView *anImageView = [[UIImageView alloc] initWithFrame: frame];
  self.imageView = anImageView;
  [self.scrollView addSubview: self.imageView];
  [self.imageView setBackgroundColor: [UIColor blueColor]];
  [self.imageView setContentMode: UIViewContentModeScaleAspectFit];

  // text view
  frame = CGRectMake(0, self.imageView.frame.size.height, 703, self.view.frame.size.width - self.imageView.frame.size.height);
  size = CGSizeMake(self.view.frame.size.height -320, self.view.frame.size.width - self.imageView.frame.size.height);
  NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize: size];
  UITextView *aTextView = [[UITextView alloc] initWithFrame: frame textContainer: textContainer];
  self.contentTextView = aTextView;
  [self.scrollView addSubview: self.contentTextView];
  self.contentTextView.delegate = self;
  self.contentTextView.editable = NO;
  self.contentTextView.hidden = NO;
  [self.body setBackgroundColor: [UIColor orangeColor]];
  // text characteristics
  self.contentTextView.textColor = [UIColor blueColor];
  self.contentTextView.textAlignment = NSTextAlignmentNatural;
  self.contentTextView.font = [UIFont fontWithName: @"Helvetica" size: 30];
  self.contentTextView.text = @"SOME AWESOME TEXT";
  self.contentTextView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
  // text view specific
  self.contentTextView.contentSize = size;

  // controller
  [self setEdgesForExtendedLayout:UIRectEdgeNone];

}

[Update: Solution]

When alloc/initializing a UITextView with a NSTextContainer you also need to separately initialize NSLayoutManager and NSTextStorage for the .text to stick.

Here's the updated working code

NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize: size];
NSLayoutManager *layoutManager = [NSLayoutManager new];
self.layoutManager = layoutManager;
[layoutManager addTextContainer: textContainer];
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString: kBaconIpsum];
self.textStorage = textStorage;
[textStorage addLayoutManager: layoutManager];
UITextView *aTextView = [[UITextView alloc] initWithFrame: frame textContainer: textContainer];
self.contentTextView = aTextView;
[self.scrollView addSubview: self.contentTextView];
3

There are 3 answers

2
Eric Qian On BEST ANSWER

NSTextContainer is the new feature of iOS 7.0, it defines the region where the text is laid out. And according to Apple's Documentations, it says "The new text container must be added to an NSLayoutManager object before it can be used.". I think thats why the .text is always nil.

0
Fang Chen On

It was the NSTextContainer...

I commented it out and used only a frame and text is appearing now, and it would appear .text is no longer nil. Which raises the question...How is one supposed to use NSTextContainers with UITextViews?

  // NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize: size];
  // UITextView *aTextView = [[UITextView alloc] initWithFrame: frame textContainer: textContainer];
  UITextView *aTextView = [[UITextView alloc] initWithFrame: frame];
  self.contentTextView = aTextView;
0
Greg On

The question is a bit old but it helped me fix a similar problem trying to format text in a scrollView and led me to Figure 1. Creating and configuring the non-view text objects. For what it's worth ...

-(id)makeHelpPage1:(CGRect)rect
{
    page1 = [[UIView alloc] initWithFrame:rect];

//    NSString *help = [scrollHelp objectAtIndex:1];
    NSString *help = @"SOME AWESOME TEXT";

    HelpTextView *showHelp = [[HelpTextView alloc] formatHelpTextNew:(NSString*)help];
    [page1 addSubview:showHelp];
    return page1;
}


#import "HelpTextView.h"

@implementation HelpTextView

-(id)formatText:(NSString*)messageID
{

// TextKit - non-view

    NSTextStorage *textStorage;
    NSLayoutManager *layoutManager;
    NSTextContainer *textContainer;

    textStorage = [[NSTextStorage alloc] initWithString:(NSString*)messageID];

    layoutManager = [[NSLayoutManager alloc] init];
    textContainer = [[NSTextContainer alloc] init];
    [layoutManager addTextContainer:textContainer];
    [textStorage addLayoutManager:layoutManager];

// TextKit - as viewed

    UITextView *textView = [[UITextView alloc] initWithFrame: textFrame textContainer: textContainer];
    return textView;
}

Disclaimer: text is unformatted