I'm having some problems setting a custom NSView for my NSPopupButton menu items. Here is what I've got so far:
#interface ViewController ()
#property (weak) IBOutlet NSPopUpButton *popupButton;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
for(int i = 0; i < 25; i++) {
NSMenuItem *menuItem = [[NSMenuItem alloc ] initWithTitle:[NSString stringWithFormat:#"%d", i] action:#selector(itemClicked:) keyEquivalent:#""];
MenuView *menuView = [[MenuView alloc] initWithFrame:CGRectMake(0, 0, 184, 50)];
menuView.displayText.stringValue = #"This is a test";
[menuItem setView:menuView];
[self.popupButton.menu addItem:menuItem];
}
}
- (void)itemClicked:(id)sender {
}
#end
//My custom view
#implementation MenuView
- (id)initWithFrame:(NSRect)frameRect {
NSString* nibName = NSStringFromClass([self class]);
self = [super initWithFrame:frameRect];
if (self) {
if ([[NSBundle mainBundle] loadNibNamed:nibName
owner:self
topLevelObjects:nil]) {
[self configureView];
}
}
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
[self configureView];
}
- (void)configureView {
[self setWantsLayer:YES];
self.layer.backgroundColor = [NSColor blueColor].CGColor;
}
#end
//Here is what my xib MenuView looks like
And here is the problem:
This seems like it should be a fairly straight forward task but I'm not sure what is happening to my view and why my label on the view seems to disappear and is not showing any text for each of the views. I was poking around in the documentation and stumbled across this for the NSPopupButton Menu :
// Overrides behavior of NSView. This is the menu for the popup, not a context menu. PopUpButtons do not have context menus.
#property (nullable, strong) NSMenu *menu;
I'm not sure if there is something that I'm doing wrong that is causing this problem or if what I'm trying to do in this context is not achievable off of an NSPopupButton NSMenu. If anyone has any experience with this and could offer advice I'd really appreciate it.
Related
Today I'm facing a new problem:
I have a ViewController (Subclass of NSView) and another class (Subclass of NSObject) which, through an IBAction, try to call back the viewController to redraw its view using SetNeedsDisplay:YES.
The method to redraw the view (ViewController.m) is:
- (void) redrawView {
[self setNeedsDisplay:YES]
}
// With an NSLog i see that the method is called !
// Instead of self i tried even an outlet connected to the custom view.
}
What I'm doing to call the ViewController method through my other class is:
1) #import "ViewController.h"
2) into the IBAction i made a new istance of ViewController as:
ViewController *newIstanceOfViewController = [[ViewController alloc] init]
3) [newIstanceOfViewController redrawView]
The log show me that setNeedsDisplay is called but drawrect no ! Why ? I have forgotten to init or subview something ? Thanks
THE ORIGINAL CODE HERE (DIFFERENT NAME OF METHODS DUE TO LANGUAGE, SAME SYNTAX)
// Controller.h
#import <Cocoa/Cocoa.h>
#interface Controller : NSView {
IBOutlet NSView *tastierinoView;
}
- (void) aggiornaTastierinoView;
#end
// Controller.m
#import "Controller.h"
#implementation Controller
//Contatore numero volte disegno view
int contatore = 0;
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
tastierinoView = [[NSView alloc] init];
}
return self;
}
- (void) aggiornaTastierinoView { //THIS IS THE METHOD TO CALL REDRAW
[tastierinoView setNeedsDisplay:YES];
NSLog(#"Chiamo setneedsDisplay\n\n");
}
- (void)drawRect:(NSRect)dirtyRect
{
contatore++;
NSLog(#"La view è stata disegnata %d volte\n\n",contatore);
[super drawRect:dirtyRect];
// Drawing code here.
NSBezierPath* percorso = [NSBezierPath bezierPath];
[[NSColor cyanColor] set];
[percorso moveToPoint:NSMakePoint(150, 150)];
[percorso lineToPoint:NSMakePoint(250, 150)];
[percorso setLineWidth:5.0];
[percorso stroke];
}
#end
// ManipolatorePin.h
#import <Foundation/Foundation.h>
#interface ManipolatorePin : NSObject {
IBOutlet NSWindow *finestraPrincipaleWindow;
IBOutlet NSTextField *codiceTextField;
NSArray *coordinate_x;
NSArray *coordinate_y;
//L'array sotto riportato serve, tramite un ciclo for, a salvare il codice pin spezzato in singoli numeri che corrisponderanno al punto.
NSMutableArray *numeroAllaIndexArray;
}
- (IBAction)aggiornaTastierino:(id)sender;
#end
// ManipolatorePin.m
#import "ManipolatorePin.h"
#import "Controller.h"
#implementation ManipolatorePin
- (void)awakeFromNib {
coordinate_x = [[NSArray alloc] initWithObjects:#"150",#"50",#"150",#"250",#"50",#"150",#"250",#"50",#"150",#"250", nil];
coordinate_y = [[NSArray alloc] initWithObjects:#"50",#"150",#"150",#"150",#"250",#"250",#"250",#"350",#"350",#"350", nil];
numeroAllaIndexArray = [[NSMutableArray alloc] init];
NSLog(#"Array coordinate iniziallizato.\nTest:(%#) -> deve risultare \"50\"\n\n",[coordinate_x objectAtIndex:4]);
}
- (IBAction)aggiornaTastierino:(id)sender {
NSString *codiceString = [[NSString alloc] initWithFormat:[NSString stringWithFormat:#"%#",[codiceTextField stringValue]]];
NSLog(#"codiceTextField = %#", codiceString);
int lunghezzaCodiceString;
NSLog(#"Il codice risulta essere composto da (%d) numeri\n\n",[codiceString length]);
//Svuoto array
[numeroAllaIndexArray removeAllObjects];
for (lunghezzaCodiceString = 0; lunghezzaCodiceString < [codiceString length]; lunghezzaCodiceString++) {
//Compilo array (Ci provo ahah)
NSString *carattereDelCodiceStringInEsame = [[NSString alloc] init];
carattereDelCodiceStringInEsame = [codiceString substringWithRange:NSMakeRange(lunghezzaCodiceString,1)];
NSLog(#"Aggiungo il numero (%#) all'array 'numeroAllaIndexArray'",carattereDelCodiceStringInEsame);
[numeroAllaIndexArray addObject:carattereDelCodiceStringInEsame];
}
//DEBUG - DA QUI IN POI E' CANCELLABILE
NSLog(#"\n\nCiclo for termitato\nProcesso concluso con successo\n\n\nContenuto array:");
int conteggioArray;
for (conteggioArray = 0; conteggioArray < [numeroAllaIndexArray count] ; conteggioArray++ ) {
NSLog(#"index (%d) -> (%#)",conteggioArray,[numeroAllaIndexArray objectAtIndex:conteggioArray]);
NSLog(#"\n\n");
}
//FINE DEBUG
///////////////HERE THE INSTANCE TO CALL THE CONTROLLER
Controller *istanzaGestionaleController = [[Controller alloc] init];
[istanzaGestionaleController aggiornaTastierinoView];
}
#end
It sounds like you have two unrelated instances of ViewController. You need to call redrawView on the instance that actually has a view on the screen.
In your class (which is not the NSViewController), create a property like this:
#property (nonatomic, readwrite, weak) NSViewController *vc;
When the class is instantiated:
YourClass *yourInstance = [[YourClass alloc] init];
assign the value of vc:
yourInstance.vc = self; // self is your NSViewController instance
Then when you want to trigger a redraw, you pass the command to self.vc inside your other class.
I have a view which includes two subviews. I had it working so that only one subview was shown at a time and each subview had a button and when the button was clicked the subview would flip over and the next subview would appear. The problem was that it appeared as though the entire view was flipping. After reading on this site about how to solve the problem I attempted to add the subviews to a container and flip that instead. However now, although my first subview is showing up when I press the button it no longer flip. It doesn't do anything. I put a log statement in the method which flips the subviews, as well as a breakpoint and as far as I can tell it no longer gets called. I'm very new to xcode and objective c and delegates and I have no idea how to proceed. Any help would be appreciated. Thanks.
I have included the relevant code here:
The header for the ViewController
#interface ExerciseViewController : UIViewController<ExerciseSubViewDelegate>
//stuff for subviews
#property (nonatomic, strong) ExerciseSubViewImage *subViewImage;
#property (nonatomic, strong) ExerciseSubViewText *subViewText;
#property UIView *panel;
#end
This is the code for the ViewController:
#interface ExerciseViewController ()
#end
#implementation ExerciseViewController
#synthesize subViewImage, subViewText;
- (void)viewDidLoad
{
self.subViewImage.delegate = self;
_panel = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.bounds.size.width, self.view.bounds.size.height/2)];
_panel.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_panel];
[_panel addSubview:subViewImage];
}
-(ExerciseSubViewImage *)subViewImage
{
if (!subViewImage)
{
CGRect subViewImageFrame = CGRectMake(0,0, _panel.bounds.size.width, _panel.bounds.size.height);
self.subViewImage = [[ExerciseSubViewImage alloc] initWithFrame:subViewImageFrame];
[_panel addSubview:subViewImage];
}
return subViewImage;
}
-(ExerciseSubViewText *)subViewText
{
if (!subViewText)
{
CGRect subViewTextFrame = CGRectMake(0,0, _panel.bounds.size.width, _panel.bounds.size.height);
self.subViewText = [[ExerciseSubViewText alloc] initWithFrame:subViewTextFrame];
self.subViewText.backgroundColor = [UIColor blueColor];
[_panel addSubview:subViewText];
}
return subViewText;
}
-(void)exerciseSubViewImagePressed
{
[UIView transitionWithView:_panel
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[subViewImage removeFromSuperview];
[_panel addSubview:subViewText];
}
completion: nil];
//This is how I did it before I added the container
/*[UIView transitionFromView:subViewImage
toView:subViewText
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromRight
completion:nil];
self.subViewText.delegate = self;*/
NSLog(#"Ipushedtheimage");
}
-(void)exerciseSubViewTextPressed
{//I haven't updated this yet
[UIView transitionFromView:subViewText
toView:subViewImage
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromRight
completion:nil];
self.subViewImage.delegate = self;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
subViewImage = nil;
subViewText = nil;
}
#end
This is the code for the delegate
#import
#protocol ExerciseSubViewDelegate <NSObject>
-(void) exerciseSubViewImagePressed;
-(void) exerciseSubViewTextPressed;
#end
I am also added the code for the first subview:
#import
#import "ExerciseSubViewDelegate.h"
#interface ExerciseSubViewImage : UIView
#property (nonatomic, strong) UIButton *button;
#property (nonatomic, assign) id<ExerciseSubViewDelegate>delegate;
#property (strong, nonatomic) UIImageView *exerciseImageView;
#end
#import "ExerciseSubViewImage.h"
#import "UIImage+animatedGIF.h"
#implementation ExerciseSubViewImage
#synthesize button;
#synthesize delegate;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//Initialization code
self.button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
CGRect buttonFrame = CGRectMake(50,200,100,35);
self.button.frame = buttonFrame;
[self.button setTitle:#"Image"forState:UIControlStateNormal];
[self.button addTarget:self
action:#selector(buttonTouched)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.button];
_exerciseImageView = [[UIImageView alloc] initWithFrame:CGRectMake(50,20,160,158)];
NSURL *url = [[NSBundle mainBundle] URLForResource:#"AppleLogo" withExtension:#"gif"];
_exerciseImageView.image = [UIImage animatedImageWithAnimatedGIFURL:url];
[self addSubview:self.exerciseImageView];
}
return self;
}
-(void)buttonTouched
{
NSLog(#"imagebuttonpressed");
[self.delegate exerciseSubViewImagePressed];
}
Again, any help would be appreciate. I know I'm probably just not understanding something simple.
Ok. This took me all weekend but I finally figured it out on my own. I thought I would shere the answer here in case anyone else ever has a similar problem. After trying several other approaches I finally went back to the approach I used here and started inserting a whole bunch of NSLogs to determine the order that every thing was executing in. What I finally ended up doing was changing this: (all in the top ViewController)
self.subViewImage.delegate = self;
_panel = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.bounds.size.width, self.view.bounds.size.height/2)];
_panel.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_panel];
[_panel addSubview:subViewImage];
to this:
//create panel
_panel = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.bounds.size.width, s self.view.bounds.size.height/2)];
_panel.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_panel];
[_panel addSubview:subViewImage];
//Set the subview delegates
self.subViewImage.delegate = self;
self.subViewText.delegate = self;
I'm using the J4n0 Callout code (github), to implement a custom annotation in MapKit.
In my annotation (MyCalloutView) I'm using a button and a label.
When I'm clicking on my button, the methode handleTouch is called, but the sender correspond an UITapGestureRecognizer with sender.view always equal to my annotation view, and not the button.
MyCalloutView.h
#interface MyCalloutView : CalloutView
#property (nonatomic, retain) IBOutlet UILabel* title;
#property (weak, nonatomic) IBOutlet UIButton *clickButton;
- (IBAction) handleTouch:(id)sender;
- (id) initWithAnnotation:(CalloutAnnotation*)annotation;
- (IBAction)onClickButton:(id)sender;
#end
MyCalloutView.m
#implementation MyCalloutView
-(IBAction) handleTouch:(UITapGestureRecognizer *)sender {
//LogDebug(#"touch from : %#", sender);
UIButton *senderButton = (UIButton *)sender.view;
LogDebug(#"Sender class : %# - Sender Tag : %d - Sender View class : %#", [sender class], sender.view.tag, sender.view.class);
LogDebug(#"Tap postion : (%f, %f)", [sender locationInView:sender.view].x, [sender locationInView:sender.view].y);
if(senderButton == self.clickButton){
LogDebug(#"le clique vient de click button !!");
}
}
[...]
CalloutView.h
#class CalloutAnnotation;
#interface CalloutView : BaseCalloutView
- (IBAction) handleTouch:(id)sender;
- (id)initWithAnnotation:(CalloutAnnotation*)annotation;
#end
CalloutView.m
#implementation CalloutView
-(IBAction) handleTouch:(id)sender {
LogDebug(#"touch %#", sender);
}
- (id)initWithAnnotation:(CalloutAnnotation*)annotation
{
NSString *identifier = NSStringFromClass([self class]);
self = [super initWithAnnotation:annotation reuseIdentifier:identifier];
if (self!=nil){
[[NSBundle mainBundle] loadNibNamed:identifier owner:self options:nil];
}
// prevent the tap and double tap from reaching views underneath
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTouch:)];
[self addGestureRecognizer:tapGestureRecognizer];
UITapGestureRecognizer *doubletapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTouch:)];
doubletapGestureRecognizer.numberOfTapsRequired = 2;
[self addGestureRecognizer:doubletapGestureRecognizer];
return self;
}
#end
This issue was a well known one. The solution is described in the GitHub : issue 1
The solution works for me.
So, i have a UITableView split in 3 sections. I want to be able, once i opened up the second row in the first section (i.e.), to swipe left to go to the next cell, and to swipe right to go the previous cell.
I wrote the code for the swipe:
SecondDetailView.m
- (void)viewDidLoad
{
UISwipeGestureRecognizer *swipeRecognizerLeft = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeDetectedLeft:)];
swipeRecognizerLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeRecognizerLeft];
[swipeRecognizerLeft release];
UISwipeGestureRecognizer *swipeRecognizerRight = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeDetectedRight:)];
swipeRecognizerRight.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swipeRecognizerRight];
[swipeRecognizerRight release];
}
- (void)swipeDetectedRight:(UIGestureRecognizer *)sender {
NSLog(#"Right Swipe");
}
- (void)swipeDetectedLeft:(UIGestureRecognizer *)sender {
NSLog(#"Left Swipe");
}
How can i do that? Is it right to put the code into the Detail View?
I have a very simple solution for your issue.
You need to declare an NSMutableArray *arr; in your .h file and assign your array to this array when you are moving to detail page.
And also you need to declare an NSString *currentPos; variable.
- (void)swipeDetectedRight:(UIGestureRecognizer *)sender {
currentPos--;
NSMutableDictionary *dic=[arr objectAtIndex:currentPos];
}
- (void)swipeDetectedLeft:(UIGestureRecognizer *)sender {
currentPos++;
NSMutableDictionary *dic=[arr objectAtIndex:currentPos];
}
In this way you can get your next and prev index values of array.
Hope this help for you.
Shivam
In my example I use NSString as my data that will be displayed in detail view controller. Feel free to change that to whatever suits your needs. Okay so here we go:
First declare a protocol in DetailViewController like so:
#class DetailViewController;
#protocol DetailViewControllerDelegate <NSObject>
- (void)swipeToNextCell:(DetailViewController *)sender;
- (void)swipeToPreviousCell:(DetailViewController *)sender;
#end
#interface DetailViewController : UIViewController
#property(weak, nonatomic) id<DetailViewControllerDelegate> delegate;
#property(copy, nonatomic) NSString *data;
#property(weak, nonatomic) IBOutlet UILabel *label;
#end
The next thing is to add UISwipeGestureRecognizers in DetailViewController to check for gestures:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UISwipeGestureRecognizer *leftGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeDetectedLeft:)];
leftGesture.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:leftGesture];
UISwipeGestureRecognizer *rightGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeDetectedRight:)];
rightGesture.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:rightGesture];
}
Implement viewWillAppear to display your data when you push your DetailViewController:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.label.text = self.data;
}
Don't forget to implement methods that will be called by GestureRecognizers:
- (void)swipeDetectedRight:(UISwipeGestureRecognizer *)sender
{
NSLog(#"Right Swipe");
[self.delegate swipeToNextCell:self];
self.label.text = self.data;
}
- (void)swipeDetectedLeft:(UISwipeGestureRecognizer *)sender
{
NSLog(#"Left Swipe");
[self.delegate swipeToPreviousCell:self];
self.label.text = self.data;
}
And thats all you need in your Detail View. Now go to the TableViewController. Your TableViewController should implement the DetailViewControllerDelegate protocol:
#interface CustomTableViewController : UITableViewController <DetailViewControllerDelegate>
#property(strong, nonatomic) DetailViewController *detailViewController;
#property(assign, nonatomic) NSInteger currentRow;
#end
Here is my getter for detailViewController #property:
- (DetailViewController *)detailViewController
{
if (_detailViewController == nil)
{
_detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
_detailViewController.delegate = self;
}
return _detailViewController;
}
Here is how I manage row selection:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *viewController = self.detailViewController;
viewController.data = [NSString stringWithFormat:#"Cell: %d", indexPath.row];
viewController.title = #"Detail";
self.currentRow = indexPath.row;
[self.navigationController pushViewController:viewController animated:YES];
}
The last thing you have to do is to implement protocol's methods:
- (void)swipeToNextCell:(DetailViewController *)sender
{
// Get data for next row
sender.data = [NSString stringWithFormat:#"Cell: %d", ++self.currentRow];
}
- (void)swipeToPreviousCell:(DetailViewController *)sender
{
// Get data for next row
sender.data = [NSString stringWithFormat:#"Cell: %d", --self.currentRow];
}
I tested it on simulator and worked fine. It is very simple as my data model is quite simple - it is just NSString. There is no checking whether there is any row in section so you have to figure that out yourself. But the whole delegation pattern should be the same.
Good luck!
Declare a protocol in the detail view controller and set the parent (which should be the table view controller) as the delegate. Then, in the swipe methods call the delegate and implement the necessary code for changing the selected row.
I have view controllers A(FileListViewController) and B(TextFileViewController). A is a UITableViewController. What I am doing now is that after selecting a row in controller A, I load a text file and display that text in a UITextView in controller B.
The following is the header and implementation part(some code is abridged) of my the two controllers.
FileListViewcontroller Interface:
#interface FileListViewController : UITableViewController {
NSMutableArray * fileList;
DBRestClient* restClient;
TextFileViewController *tfvc;
}
#property (nonatomic, retain) NSMutableArray * fileList;
#property (nonatomic, retain) TextFileViewController *tfvc;
#end
FileListViewController Implementation:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DBMetadata *metaData = [fileList objectAtIndex:indexPath.row];
if(!metaData.isDirectory){
if([Utils isTextFile:metaData.path]){
if(!tfvc){
tfvc = [[TextFileViewController alloc] init];
}
[self restClient].delegate = self;
[[self restClient] loadFile:metaData.path intoPath:filePath];
[self.navigationController pushViewController:tfvc animated:YES];
}
}
- (void)restClient:(DBRestClient*)client loadedFile:(NSString*)destPath {
NSError *err = nil;
NSString *fileContent = [NSString stringWithContentsOfFile:destPath encoding:NSUTF8StringEncoding error:&err];
if(fileContent) {
[tfvc updateText:fileContent];
} else {
NSLog(#"Error reading %#: %#", destPath, err);
}
}
And here is the interface for TextFileViewController:
#interface TextFileViewController : UIViewController {
UITextView * textFileView;
}
#property (nonatomic, retain) IBOutlet UITextView * textFileView;
-(void) updateText:(NSString *) newString;
#end
TextFileViewController implementation:
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(done)] autorelease];
textFileView = [[UITextView alloc] init];
}
- (void) updateText:(NSString *)newString {
NSLog(#"new string has value? %#", newString);
[textFileView setText:[NSString stringWithString:newString]];
NSLog(#"print upddated text of textview: %#", textFileView.text);
[[self textFileView] setNeedsDisplay];
}
(void)restClient: loadedFile: will be call after the loadFile:intoPath: is completed in the disSelectRowAtIndexPath method.
In TextFileViewController's updateText method, from NSLog I see that the text property is updated correctly. But the screen does not update accordingly. I've tried setNeedsDisplay but in vain. Did I miss something?
Thanks in advance.
In -[TextFileViewController viewDidLoad] you're creating a UITextView, but its frame is never set, and it's not added to the view hierarchy.
Try changing this:
textFileView = [[UITextView alloc] init];
to this:
textFileView = [[UITextView alloc] initWithFrame:[[self view] bounds]];
[[self view] addSubview:textFileView];
The problem is that textFileView is created in the viewDidLoad method of TextFileViewController. This method has not yet been called by the time you call updateText (this happens before the TextFileViewController is pushed).
You can fix this by forcing the view to load before you call [[self restClient] loadFile:metaData.path intoPath:filePath];.