label property is nil,container view - objective-c

Situation:
3 view controllers, white is main, red and blue are embedded (container view controllers)
I select something in red,it switches to blue,I swipe the blue - it goes back and I want to change text in the label to some custom text
Sequence:
So I use delegation and it also works.But when I try to set label's text property(in the method that confirms my protocol) via self.thisLabel.text NSLog says this label is nil, although I have an outlet. If I use something like [self.view viewWithTag:tag] NSLog shows that label is there but I can't set the text, it stays the same.
code in white:
header
#interface ContactsViewController : UIViewController <BlueViewControllerDelegate>
implementation
- (void)adjustLabel:(NSString *)string{
NSLog(#"i am here baby %#",self.thisLabel);
[[self.view viewWithTag:57] setValue:string forKey:#"text"];
}
code in blue:
header:
#protocol BlueViewControllerDelegate <NSObject>
-(void)adjustLabel:(NSString*)string;
#end
and:
#property id<ViewControllerDelegate> delegate;
implementation
- (void)viewDidLoad{
[super viewDidLoad];
UIStoryboard *sB = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
WhiteViewController *WhiteVc = [sB instantiateViewControllerWithIdentifier:#"whiteID"];
self.delegate = WhiteVc;
}
-(void)willMoveToParentViewController:(UIViewController *)parent{
[self.delegate adjustLabel:#"some custom text"];
}
-(IBAction)swipePerformed:(UISwipeGestureRecognizer*)sender{
[self willMoveToParentViewController:nil];
[self.view removeFromSuperview];
[self removeFromParentViewController];
}
Any thoughts?

If I understand your VC hierarchy correctly, the WhiteViewController is the parent of BlueViewController, so you shouldn't instantiate a new one from the storyboard in viewDidLoad but do instead:
WhiteViewController *whiteVc = (WhiteViewController*)self.parentViewController;
self.delegate = whiteVC;
Also, I don't find overriding willMoveToParentViewController particularly useful. You could put your delegate call to your swipe action.

Related

Can't set a label in a view

I have the following situation. I have a view controller (ContentController) with 3 buttons at the top. Below I added a second view (contentView), this view should display content that are behind those 3 buttons. So every time I press a button, the contentView changes. So what I did was created three addition controllers.
FirstController.m, FirstController.h, FirstController.xib
SecondController.m, SecondController.h, SecondController.xib,
ThirdController.m, ThirdController.h, ThirdController.xib,
in my ContentController.m I added 3 IBActions that handles the change.
#interface ViewController ()
#property (nonatomic,strong) UIViewController *nextController;
#end
#implementation ViewController
#synthesize nextController = _nextController;
-(IBAction)chooseFirstController:(id)sender {
_nextController = [[FirstController alloc] initWithNibName:#"FirstController" bundle:nil];
[self.contentView addSubview:_nextController.view];
}
-(IBAction)chooseSecondController:(id)sender{
_nextController = [[SecondController alloc] initWithNibName:#"SecondController" bundle:nil];
[self.contentView addSubview:_nextController.view];
}
-(IBAction)chooseThirdController:(id)sender{
_nextController = [[ThirdViewController alloc] initWithNibName:#"ThirdViewController" bundle:nil];
[self.contentView addSubview:_nextController.view];
}
My first and ThirdController just showing tableviews inside the contentView of contentController. But in my secondController I used a gridView for displaying items. Now when I press a cell, it should go to a detailViewController, whichs shows more information about that cell. So in my cellForRowAtIndex I did the following.
- (void)gridView:(NRGridView *)gridView didSelectCellAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cell clicked");
PlayerDetailController *playerController = [[PlayerDetailController alloc]initWithNibName:#"PlayerDetailController" bundle:nil];
[playerController setLblTest:#"hooray this works"];
[self.view addSubview:playerController.view];
}
It correctly executes setLblTest and also showing the detailViewcontroller inside my ContentView. But it don't changes the label. to my #"hooray" this works. But although as you can see in my log it passes it correctly.
#synthesize testLabel = _testLabel;
#synthesize lblTest = _lblTest;
-(void)setLblTest:(NSString *)lblTest{
if(![_lblTest isEqual:lblTest]){
_lblTest = lblTest;
}
NSLog(#"log komt %#",lblTest);
[_testLabel setText:lblTest];
}
LOG
RacingGenk[567:c07] log komt hooray this works
Hope this clarifies more my problem
Thank you
To get the label to update, you'll need to change your code to look like this.
self.testLabel.text = lblTest;

Passing data to a UIView - failure

I have a strange problem that I've never encountered before,
I have data in my viewController that I want to display in a UIView.
It's an iPad App which involve a SplitView Controller, when I click on an element within the table view (masterView) it execute a function in my detailViewController (via a protocol).
A function is executed which launch a UIView and send data to it:
myController:
- (void)SelectionChanged:(DocumentInfo*)document_info withDocu:(Document *)document{
DocumentView *viewDoc=[[DocumentView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
viewDoc.doc=document;
viewDoc.doc_info=document_info;
[viewDoc setBackgroundColor:[UIColor whiteColor]];
[self.view addSubview:viewDoc];
}
DocumentView.h
#import <UIKit/UIKit.h>
#import "Document.h"
#import "DocumentInfo.h"
#class Document;
#class DocumentInfo;
#interface DocumentView : UIView
#property(strong,nonatomic) Document *doc;
#property(strong,nonatomic) DocumentInfo *doc_info;
#end
DocumentView.m
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UILabel *titreDoc=[[UILabel alloc] initWithFrame:CGRectMake(20, 32, 339, 21)];
titreDoc.textColor = [self makeColorRGB_RED:66 GREEN:101 BLUE:149];
titreDoc.font = [UIFont fontWithName:#"System" size:(24.0)];
[self addSubview:titreDoc];
NSLog(#"%# - %#",doc,doc_info);
titreDoc.text=#"Nouveau Document";
}
return self;
}
My view is well displayed (I mean the label appear) but impossible to get the data which would have been passed to it... (the NSLog print (null) (null) )
Anybody know the reason why?
The problem seems pretty straight forward. You initialize your view (which means that you run - (id)initWithFrame:(CGRect)frame) and after that you're setting the data, so it's normal that you see null values into your init method because the ivars have not being set yet. What you could do is to modify your init method in order to construct your view taking into account these ivars. Something like this perhaps:
- (id)initWithFrame:(CGRect)frame doc:(Document *)doc docInfo:(DocumentInfo *)docInfo;
ps. If you choose to make your custom init method do not forget to call the designated initializer (-initWithFrame:) before any customization.
The reason the NSLog prints null is because the doc and doc_info are nil when the initWithFrame method is called. The doc and doc_info properties are set after the initWithFrame method is called in selectionChanged: method. Add the NSLog function after line 3 in selectionChanged method like this:
- (void)SelectionChanged:(DocumentInfo*)document_info withDocu:(Document *)document{
DocumentView *viewDoc=[[DocumentView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
viewDoc.doc=document;
viewDoc.doc_info=document_info;
NSLog(#"%# - %#",doc,doc_info);
[viewDoc setBackgroundColor:[UIColor whiteColor]];
[self.view addSubview:viewDoc];
}

Different transparencies in Cocoa?

I have overloaded NSWindow and have created a custom window of my own (Borderless and transparency of 0.3 alphaValue). I am going to be drawing images in this window. Is there any way I can get the images that will be drawn in the window opaque? I want the window to remain transparent but want the images to be opaque. How would I do this?
Mac OS X Snow Leopard
Xcode 3.2.6
#ughoavgfhw is on the right track, but it's actually much easier. You just need to set opaque to NO and set backgroundColor to semi-transparent.
#implementation MYWindow
- (void)setup
{
[self setStyleMask:NSBorderlessWindowMask];
[self setOpaque:NO];
[self setBackgroundColor:[NSColor colorWithCalibratedWhite:1.0 alpha:0.3]];
}
// We override init and awakeFromNib so this works with or without a nib file
- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
{
self = [super initWithContentRect:contentRect styleMask:aStyle backing:bufferingType defer:flag];
if (self)
{
[self setup];
}
return self;
}
- (void)awakeFromNib
{
[super awakeFromNib];
[self setup];
}
#end
There's a potential problem with this approach.
Requesting "[self setStyleMask:NSBorderlessWindowMask];" (with any of the possible StyleMask values) will cause the loss of keystroke events to that window on subsequent presentations of the window as a sheet. I reported a bug to Apple today on this point.
Leave the alphaValue property to 1, and set the opaque property to NO. Then, replace the default contentView with one which fills itself with a color whose alpha component is 0.3 in its drawRect: method. When you change the alphaValue property, it changes how everything drawn in the window is displayed. When you make it non-opaque, it simply doesn't draw a black background beneath the content view, so if the content view is transparent, the window will be too, but anything drawn on top of that will not be affected.
Here's an example which uses a white background with a 0.3 alpha component. Note that I overrode the setContentView: method. This is so that I can copy any views from the passed view into the transparent content view, and is especially necessary if you load the window from a nib, since the nib loading will change the content view when it is loaded. (You could change the content view's class in IB instead.)
#interface MyWindow_ContentView : NSView
#end
#implementation MyWindow
- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag {
if(self = [super initWithContentRect:contentRect styleMask:aStyle backing:bufferingType defer:flag]) {
[super setOpaque:NO];
[super setContentView:[[[MyWindow_ContentView alloc] init] autorelease]];
}
return self;
}
- (void)setOpaque:(BOOL)ignored {}
- (void)setContentView:(NSView *)newView {
NSArray *views = [[self.contentView subviews] copy];
[views makeObjectsPerformSelector:#selector(removeFromSuperview)];
views = [[newView subviews] copy];
[views makeObjectsPerformSelector:#selector(removeFromSuperview)];
for(NSView *view in views) [self.contentView addSubview:view];
[views release];
}
#end
#implementation MyWindow_ContentView
- (void)drawRect:(NSRect)rect {
[[NSColor colorWithCalibratedWhite:1 alpha:0.3] set];
NSRectFill(rect);
}
#end

Problems with storyboard

recently I started using storyboard and I've the following situation: I want to set the text of an UILabel from the AppDelegate. So I created an instance of my ViewController
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle: nil];
ViewController *controller = (ViewController*)[mainStoryboard
instantiateViewControllerWithIdentifier: #"mainViewController"];
myViewController = controller;
[window addSubview:myViewController.view];
[window makeKeyAndVisible];
and called the following method from the delegate
- (void) updateParameterLabel:(NSString *)parameter {
NSLog(#"URL-2: %#", parameter);
parameterLabel.text = parameter;
}
But the parameter is not shown in the UI.
Another think, which is kind of strage:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(#"View did Appear");
}
The "View did appear" is logged twice ...
Any hints?
Regards,
Sascha
Setting the text of a UILabel from your application delegate isn't great design. Your view controllers should be managing the content of your views, hence their name. Typically your storyboard is instantiated automatically, and you don't need any of the storyboardWithName et code you've got, assuming you're working with Apple's default templates.
Maybe think about re-architecting your application to follow the 'model-view-controller' pattern more strictly, and also look at how Apple instantiate storyboards automatically (just create a new storyboard project in XCode to see this).
If you still want to make it work, make the UILabel a property of your viewcontroller and set the label by using
In delegate :
- (void) updateParameterLabel:(NSString *)parameter {
NSLog(#"URL-2: %#", parameter);
[myViewController updateParemeter:parameter];
}
In myViewController:
- (void) updateParameterLabel:(NSString *)parameter {
NSLog(#"URL-2: %#", parameter);
parameterLabel.text = parameter;
[self.view setNeedsDisplay];//edit
}
So use the viewController to update your label. Of course you need the label as a property in your viewController
For what I see you are trying to update the label before it appears, so why don't you try calling your updateLabel method in the viewWillAppear, it would be something like this
-(void)viewWillAppear:(BOOL)animated{
[self updateParameterLabel:#"Some Text"];
[super viewWillAppear:YES];
}
And updateParameterLabel has to be implemented in the viewController.

firstResponder in NSViewController

I've got two classes. ManagingViewController, a subclass of NSViewController, and ViewController, a subclass auf ManagingViewController. In Viewcontroller I've got a NSTextField which I want to become the firstResponder, but I didn't manage that.
So it is nearly the same like the Chapter 29 in Hillegass' book Cocoa Programming for Mac OS X (Download of the book's examples) except of an NSTextField which is set to firstResponder.
Can anybody point me to the correct way?
You need to set the text field as the first responder by using -[NSWindow makeFirstResponder:].
Since this is an NSWindow method, it only makes sense after you’ve added the corresponding view to the window, i.e., after you’ve added the view as a subview inside the window view hierarchy. In the book’s example, this happens when you set the view as the content view of the box inside the window. For example:
- (void)displayViewController:(ManagingViewController *vc) {
// Try to end editing
NSWindow *w = [box window];
…
// Put the view in the box
NSView *v = [vc view];
[box setContentView:v];
// Set the first responder
if ([vc class] == [ViewController class]) {
[w makeFirstResponder:[(ViewController *)vc myTextField]];
}
}
This assumes ViewController exposes a getter method called -myTextField.
You can make this more generic by having your view controllers expose a method that returns the object that the view controller recommends as the first responder. Something like:
#interface ManagingViewController : NSViewController
…
- (NSResponder *)recommendedFirstResponder;
#end
#implementation ManagingViewController
…
- (NSResponder *)recommendedFirstResponder { return nil; }
#end
And, in your concrete subclasses of ManagingViewController, have -recommendedFirstResponder return the object that should be the window’s first responder:
#implementation ViewController
…
- (NSResponder *)recommendedFirstResponder { return myTextField; }
#end
Having done that, you can change your -displayViewController: to something like:
- (void)displayViewController:(ManagingViewController *vc) {
// Try to end editing
NSWindow *w = [box window];
…
// Put the view in the box
NSView *v = [vc view];
[box setContentView:v];
// Set the first responder
NSResponder *recommendedResponder = [vc recommendedFirstResponder];
if (recommendedResponder) [w makeFirstResponder:recommendedResponder];
}
Have you tried [[myTextField window] makeFirstResponder:myTextField]; ?
simple. Goto you xib file in interface builder. right click the first responder field. it will show the connection , remove the connection and connect it to the desired responder. let me know if this works