Multiple windows mac application - objective-c

I want to make a multiple windows mac application and I am stuck with the multiple window part !
I can display some windows by creating a xib file and using this method :
-(void)popView:(NSString *)viewName {
_windowController = [[AddProdutWindowController alloc] initWithWindowNibName:viewName];
[_windowController showWindow:nil];
}
With
#property (strong, nonatomic) AddProdutWindowController *windowController;
in my header file and AddProductViewController inherit from NSWindowViewController
I have linked a subclass of NSViewController in Xcode to my xib file.
Now I want to send some datas to my new view and show them in some NSTextField and I have not a single clue how to do it !
I'm very confused with the WindowsController and ViewController, I don't exactly know how / where use them.
Thank you for helping.

Try this:
your firstWindowController.h:
#import <Cocoa/Cocoa.h>
#class SecondWindowController;
#interface ResultWindowController : NSWindowController{
SecondWindowController *swc;
}
#property (assign) NSNumber *xyz;
...
your firstWindowController.m:
#import "FirstWindowController.h"
#import "SecondWindowController.h"
#implementation FirstWindowController
#synthesize xyz;
- (IBAction)openSecondWindow:(id *)sender {
if (!swc)
{
swc = [[SecondWindowController alloc] init];
}
[Swc setFwc:self];
[Swc showWindow:self];
your secondWindowController.h:
#import <Cocoa/Cocoa.h>
#class FirstWindowController;
#interface SecondWindowController : NSWindowController {
FirstWindowController *fwc;
}
#property (retain) IBOutlet FirstWindowController *fwc;
#end
your secondWindowController.m:
#import "SecondWindowController.h"
#import "FirstWindowController.h"
#implementation SecondWindowController
#synthesize fwc;
- (id)init
{
if(![super initWithWindowNibName:#"SecondWindow"])
return nil;
NSLog(#"_init: %#", NSStringFromClass([self class]));
return self;
}
- (void)windowDidLoad
{
[super windowDidLoad];
NSLog(#"swc didload self=%p", self); //thats your second window controller
NSLog(#"fwc value is %#", fwd.xyz); // here you should be able to see the value from FirtsWindowController
}

Related

How to correctly implement a NSWindowController subclass with xib-file

I am trying to implement a NSWindowController subclass with new xib-file, I read up in lots of books, and researched on StackOverflow, but none of the steps provided made my window show, nor did the subclass code get executed. The new xib-file has its File's Owner set to "LogNavigatorController" and connections to the window and its contents have been made.
My AppDelegate.h:
#import <Cocoa/Cocoa.h>
#class LogNavigatorWindowController;
#interface AppDelegate : NSObject <NSApplicationDelegate>
{
LogNavigatorWindowController *logsWindowController;
}
#end
My AppDelegate.m:
#import "AppDelegate.h"
#import "LogNavigatorWindowController.h"
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
logsWindowController = [[LogNavigatorWindowController alloc] initWithWindowNibName:#"LogNavigatorWindowController"];
[logsWindowController showWindow:self];
}
#end
My LogNavigatorWindowController.h:
#import <Cocoa/Cocoa.h>
#interface LogNavigatorWindowController : NSWindowController
{
NSArray *directoryList1;
NSArray *directoryList2;
NSMutableArray *directoryList;
NSMutableArray *filePaths1;
NSMutableArray *filePaths2;
}
#property (assign) IBOutlet NSWindow *window;
#property (weak) IBOutlet NSTableView *logsTableView;
#property (unsafe_unretained) IBOutlet NSTextView *logsTextView;
#property (assign) IBOutlet NSArrayController *LogListController;
#property (retain) NSMutableArray *logsArray;
- (void) myDirectoryLogFunction;
#end
My LogNavigatorController.m:
#import "LogNavigatorWindowController.h"
#interface LogNavigatorWindowController ()
#end
#implementation LogNavigatorWindowController
#synthesize logsTableView;
#synthesize logsTextView;
#synthesize window;
- (id)init
{
self = [super initWithWindowNibName:#"LogNavigatorWindowController"];
[self loadWindow];
[self showWindow:#"Log Navigator"];
[self.window makeKeyAndOrderFront:nil];
if (self)
{
// Initialization code here.
[self myDirectoryLogFunction];
}
return self;
}
- (void)windowDidLoad
{
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
- (void) myDirectoryLogFunction
{
NSLog(#"Code execution test successful");
}
#end
You don't need to create the window property since it is already available for NSWindowController subclasses. Maybe that causes the problem.
Also your init method contains a lot of code that doesn't belong there. Remove
[self loadWindow];
[self showWindow:#"Log Navigator"];
[self.window makeKeyAndOrderFront:nil];
as well as replace
self = [super initWithWindowNibName:#"LogNavigatorWindowController"];
with
self = [super init];
You may want to remove the init method at all, since you don't need it in your case.
and move
[self myDirectoryLogFunction];
to the windowDidLoad method.
Also always check that the code for instantiating the window controller (in your case from the app delegates didFinishLaunching: ) is called. Sometimes it helps to create a new project and test there, if you may have changed too much within the original project and by accident removed delegate connections or similar.

CALayer _layer is not getting initialized on application startup?! (OSX, Cocoa)

I'm very new to AVFoundation and QuartzCore development and I'm having troubles with CALayers. I'm sorry if this is a silly problem.
Here's my code:
.h
#import <Cocoa/Cocoa.h>
#import <AVFoundation/AVFoundation.h>
#import <QuartzCore/QuartzCore.h>
#interface Document : NSPersistentDocument
{
AVPlayer *player;
AVPlayerLayer *playerLayer;
NSView *playerView;
}
#property AVPlayerLayer *playerLayer;
#property AVPlayer *player;
#property IBOutlet NSView *playerView;
#end
.m
#import "Document.h"
#implementation Document
#synthesize playerView;
#synthesize player;
#synthesize playerLayer;
- (id)init
{
self = [super init];
if (self) {
}
return self;
}
- (NSString *)windowNibName
{
return #"Document";
}
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
[super windowControllerDidLoadNib:aController];
[[aController window] setMovableByWindowBackground:YES];
// HERE the layer is nill, and I don't understand why it's not getting initialized?!
[[[self playerView] layer] setBackgroundColor:CGColorGetConstantColor(kCGColorBlack)];
}
+ (BOOL)autosavesInPlace
{
return YES;
}
#end
Any kind of help is very appreciated!
If the layer is nil, you should start by suspecting that its parent playerView is nil. Is it? If so, you probably haven't hooked up the outlet in the nib. (I see you have declared playerView as an outlet in your code, but that doesn't mean you've configured the nib correctly.)

Objective C Protocol Delegate test

I'm studing protocol and delegates using an Example! When I try to re create this example I notice that this condition is not respected:
if([delegate respondsToSelector:#selector(amountEntered:)]) {blabla}
where is the mistake? Scripts:
First View .h
#import <UIKit/UIKit.h>
#import "EnterAmountViewController.h"
#interface DelegateExampleViewController : UIViewController <EnterAmountDelegate>{
IBOutlet UILabel *amountLabel;
}
-(IBAction)changeAmountPressed;
#end
First View .m
#import "DelegateExampleViewController.h"
#implementation DelegateExampleViewController
-(IBAction)changeAmountPressed
{
EnterAmountViewController * enterAmountVC = [[EnterAmountViewController alloc]init];
enterAmountVC.delegate = self;
}
-(void)amountEntered:(NSInteger)amount
{
amountLabel.text = [NSString stringWithFormat:#"%i" , amount];
}
#end
Second View .h
#import <UIKit/UIKit.h>
#protocol EnterAmountDelegate <NSObject>
-(void)amountEntered:(NSInteger)amount;
#end
#interface EnterAmountViewController : UIViewController {
IBOutlet UITextField *amountTextField;
id<EnterAmountDelegate> delegate;
}
-(IBAction)savePressed;
#property(nonatomic,retain) id<EnterAmountDelegate> delegate;
#end
Second View .m
#import "EnterAmountViewController.h"
#import "DelegateExampleViewController.h"
#implementation EnterAmountViewController
#synthesize delegate;
- (void)viewDidLoad {
[super viewDidLoad];
amountTextField.text = #"";
[amountTextField becomeFirstResponder];
}
-(IBAction)savePressed
{
if([delegate respondsToSelector:#selector(amountEntered:)])
{
[delegate amountEntered:[amountTextField.text intValue]];
NSLog(#"rugg");
}
}
#end
Thanks in advance!
In the method:
-(IBAction)changeAmountPressed
{
EnterAmountViewController * enterAmountVC = [[EnterAmountViewController alloc]init];
enterAmountVC.delegate = self;
}
you are creating an instance of EnterAmountViewController on the stack as a local variable. This variable will be inaccessible at the end of the scope. So, when you execute savePressed you are doing it on a different object where you did not set delegate.
In other words, when you check
if([delegate respondsToSelector:#selector(amountEntered:)])
it returns NO because delegate is nil...
The correct way to set the delegate is using the prepareForSegue mechanism:
#implementation DelegateExampleViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[(EnterAmountViewController*)segue.destinationViewController setDelegate:self];
}
...
You do not need the changeAmountPressed method nor the relative binding.

How to access view controller variables from the app delegate... and vice versa?

I would like the view controller to be able to access dog in the app delegate.
I would like the app delegate to be able to access mouse in the view controller.
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
int mouse; // <----------------
}
#end
- (void)viewDidLoad
{
[super viewDidLoad];
mouse = 12; // <-------------------
NSLog(#"viewDidLoad %d", dog); // <---------------
}
#import <UIKit/UIKit.h>
#class ViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
int dog; // <---------------
}
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) ViewController *viewController;
#end
- (void)applicationWillResignActive:(UIApplication *)application
{
NSLog(#"applicationWillResignActive %d", mouse); // <--------------
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
dog = 77; // <---------------------
NSLog(#"applicationDidBecomeActive");
}
Part 1:
In the ViewController.h:
-(int)mouse; //add this before the #end
In the ViewController.m, add this method:
-(int)mouse
{
return mouse;
}
To access mouse from AppDelegate, use self.viewController.mouse
For example;
NSLog(#"ViewController mouse: %i", self.viewController.mouse);
Part2:
In the AppDelegate.h:
-(int)dog; //add this before the #end
In the AppDelegate.m, add this method:
-(int)dog
{
return dog;
}
In the ViewController.m:
#import "AppDelegate.h"
To access dog from ViewController, use this:
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSLog(#"dog from AppDelegate: %i", [appDelegate dog]); //etc.
In your view controller header file add mouse as a property:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
NSInteger mouse; // <----------------
}
#property (nonatomic, assign) NSInteger mouse;
#end
Synthesize the property in your view controller implementation just below the #implementation line:
#synthesize mouse;
In your app delegate add dog as a property:
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
NSInteger dog; // <---------------
}
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) ViewController *viewController;
#property (nonatomic, assign) NSInteger dog;
#end
Also synthesize dog in your app delegate implementation.
Now in your app delegate, assuming you have a reference to your view controller, you can access mouse like this:
viewController.mouse = 13;
You can do the same thing with your app delegate class, which can be accessed from any view controller using (assuming the name of your app delegate class is AppDelegate):
((AppDelegate *)([UIApplication sharedApplication].delegate)).dog = 13;
I would recommend that you use also use NSInteger instead of int.

UITextField: set text from a label

I'm trying to write my first iPad app using Xcode 4: it's based on "Tabbed Application" template with two views. On the first view, user selects a City (label displays selection) and on the second wiew there is a IBOutletCollection(UITextField) NSArray *playersData. I want to set the city selected on first view as a default city on second view. I have checked storyboard connections and they seem to be ok.
I get nothing. Any idea?
First view :
#import
#interface pruebaF1FirstViewController : UIViewController
- (IBAction)selectCity:(UIButton *)sender;
#property (weak, nonatomic) IBOutlet UILabel *citySelected;
#end
First view implementation :
#import "pruebaF1FirstViewController.h"
#import "pruebaF1SecondViewController.h"
#interface pruebaF1FirstViewController ()
#property pruebaF1SecondViewController *secondView;
#end
#implementation pruebaF1FirstViewController
#synthesize citySelected;
#synthesize secondView;
- (void)viewDidLoad
...
- (IBAction)selectCity:(UIButton *)sender {
NSString *currentCity =[sender currentTitle];
citySelected.text=#"";
citySelected.text =[citySelected.text stringByAppendingString:currentCity];
/*writes null*/
secondView.defaultCity.text=[NSString stringWithFormat:#"%#" ,currentCity];
NSLog(#"%#",secondView.defaultCity.text);
}
#end
Second view header
#import <UIKit/UIKit.h>
#interface pruebaF1SecondViewController : UIViewController <UITextFieldDelegate>
#property (strong, nonatomic) IBOutletCollection(UITextField) NSArray *playersData;
#property (retain, nonatomic) IBOutlet UITextField *defaultCity;
- (IBAction)eraseData:(UIButton *)sender;
- (IBAction)savePlayersData:(UIButton *)sender;
- (IBAction)termsPopUp:(UIButton *)sender;
/*- (void)writeDefaultCity:(NSString *)currentCity;*/
#end
Second view implementation
#import "pruebaF1SecondViewController.h"
#import "pruebaF1FirstViewController.h"
#interface pruebaF1SecondViewController ()
#property (nonatomic, strong)pruebaF1FirstViewController *prueba;
#end
#implementation pruebaF1SecondViewController
#synthesize playersData;
#synthesize defaultCity;
#synthesize prueba;
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[self setPlayersData:nil];
[self setDefaultCity:nil];
[super viewDidUnload];
}
/* Return or Done button dismiss keyboard*/
-(BOOL)textFieldShouldReturn:(UITextField *)boxes
{
for (UITextField *boxes in playersData) {
[boxes resignFirstResponder];
}
return YES;
}
....
/*Trying to get city's name from first view in two ways*/
/*-(void)setDefaultCity
{
NSString *defecto=prueba.citySelected.text;
self.defaultCity.text = defecto;
}*/
- (IBAction)eraseData:(UIButton *)sender {
for (UITextField *boxes in playersData) {
boxes.text = #" ";
}
}
/*
-(void)writeDefaultCity:(NSString *)currentCity
{
defaultCity.text =[NSString stringWithFormat:#"%#" ,currentCity];
NSLog(#"Ciudad elegida: %#",currentCity);
}*/
....
#end
Views are generally not loaded until they are displayed on the device, and may be unloaded at any time when not visible to save memory. This means that when you're setting the 'text' property of the 'defaultCity', that label has not yet been created.
Instead you should add a NSString * property to pruebaF1SecondViewController and set the value of the defaultCity label in viewDidLoad:
In the header:
#property (nonatomic, weak) UILabel *defaultCityLabel;
#property (nonatomic, strong) NSString *defaultCity;
In the implementation
- (void)viewDidLoad
{
[super viewDidLoad];
defaultCityLabel.text = defaultCity;
}
And in the first view controller, assign the string value instead of the label value.