NSWindowController multiple nib problem - cocoa

MainController.h
#import <Cocoa/Cocoa.h>
#interface MainController : NSWindowController {
NSWindowController *sc;
IBOutlet NSTextField *txt1;
}
-(IBAction)executeButtonClick:(id)sender;
-(void)setTxt1Text:(NSString *)txt;
#end
MainController.m
#import "MainController.h"
#import "SecondController.h"
#implementation MainController
-(void)awakeFromNib
{
sc = nil;
}
-(IBAction)executeButtonClick:(id)sender;
{
if (sc == nil)
{
sc = [[SecondController alloc] initWithMController:self];
}
[sc showWindow:self];
[[sc window] makeKeyAndOrderFront:sender];
}
-(void)setTxt1Text:(NSString *)txt;
{
[txt1 setStringValue:txt];
}
#end
SecondController.h
#import <Cocoa/Cocoa.h>
#interface SecondController : NSWindowController {
NSWindowController *mController;
}
-(id)initWithMController:(NSWindowController *)mctrl;
-(IBAction)testButtonClick:(id)sender;
#end
Here's the problem reside:
SecondController.m
#import "SecondController.h"
#implementation SecondController
-(id)initWithMController:(NSWindowController *)mctrl;
{
self = [super initWithWindowNibName:#"SecondWindow"];
mController = mctrl;
NSLog(#"%#",mController);
return self;
}
-(IBAction)testButtonClick:(id)sender;
{
NSLog(#"%#",mController);
[mController setTxt1Text:#"Test Success"];
}
#end
Logs:
2011-05-09 15:41:10.337 MultiWindow[4334:a0f] <MainController: 0x1005295b0>
2011-05-09 15:41:11.336 MultiWindow[4334:a0f] (null)
Why mController became null ? Can anyone help ?
Thanks

Try logging self in both places as well (in addition to mController). My guess is you will find that you have more than one SecondController object (perhaps one created in code through -[MainController executeButtonClick:] and the other in your SecondWindow nib?).

Related

IKScannerDeviceView is only working once

I have an app with a main window and a secondary window with an NSScannerDeviceView in it.
The idea is to scan an image to memory and place it into an NSImageView in the main window.
So far so good. When the scanner window is opened I can scan an image and it is placed correctly in to the NSImageView.
The problem is this, I can scan again and again but if I close the scan window and re-open it the NSScannerDeviceView no longer works. I'm sure the solution is relatively simple but as I'm still learning obj-c / cocoa it's got me stumped.
The code I'm using is as follows: ScanWindowController.h
#import <Cocoa/Cocoa.h>
#import <Quartz/Quartz.h>
#import <ImageCaptureCore/ImageCaptureCore.h>
#interface ScanWindowController : NSWindowController <IKScannerDeviceViewDelegate, ICScannerDeviceDelegate, ICDeviceBrowserDelegate> {
ICDeviceBrowser *mDeviceBrowser;
}
#property (strong) IBOutlet IKScannerDeviceView *ScannerView;
#end
and: ScannerWindowController.m
#import "ScanWindowController.h"
#import "AppDelegate.h"
#interface ScanWindowController ()
#end
#implementation ScanWindowController
#synthesize ScannerView;
- (id)init
{
if ( ! (self = [super initWithWindowNibName: #"ScanWindowController"]) ) {
return nil;
}
mDeviceBrowser = [[ICDeviceBrowser alloc] init];
mDeviceBrowser.delegate = self;
mDeviceBrowser.browsedDeviceTypeMask = ICDeviceLocationTypeMaskLocal|ICDeviceLocationTypeMaskRemote|ICDeviceTypeMaskScanner;
[mDeviceBrowser start];
return self;
}
- (void)windowDidLoad
{
[super windowDidLoad];
}
- (void)windowWillClose:(NSNotification *)notification {
[mDeviceBrowser stop];
}
- (void)scannerDeviceView:(IKScannerDeviceView *)scannerDeviceView didScanToURL:(NSURL *)url fileData:(NSData *)data error:(NSError *)error
{
if(!error) {
[(AppDelegate*)[[NSApplication sharedApplication] delegate] recieveScannedData:data];
}
}
- (void)scannerDeviceDidBecomeAvailable:(ICScannerDevice*)scanner;
{
[scanner requestOpenSession];
}
- (void)deviceBrowser:(ICDeviceBrowser*)browser didAddDevice:(ICDevice*)addedDevice moreComing:(BOOL)moreComing
{
if ( (addedDevice.type & ICDeviceTypeMaskScanner) == ICDeviceTypeScanner )
{
[ScannerView setScannerDevice:(ICScannerDevice*)addedDevice];
}
}
-(void)deviceBrowser:(ICDeviceBrowser *)browser didRemoveDevice:(ICDevice *)device moreGoing:(BOOL)moreGoing
{
[device requestCloseSession];
}
-(void)didRemoveDevice:(ICDevice*)removedDevice
{
[removedDevice requestCloseSession];
}
#end
I have solved this problem (after talking to Apple), and the result is this:
The NSScannerDeviceView is activated when the window is initialised, however as this doesn't get called again and the NSScannerDeviceView is closed when the window is closed, it never gets reactivated.
The solution was to create a new method (scannerReopen) and call it each time the window is opened as follows:
#import <Cocoa/Cocoa.h>
#import <Quartz/Quartz.h>
#import <ImageCaptureCore/ImageCaptureCore.h>
#interface ScanWindowController : NSWindowController <IKScannerDeviceViewDelegate, ICScannerDeviceDelegate, ICDeviceBrowserDelegate> {
ICDeviceBrowser *mDeviceBrowser;
}
#property (strong) IBOutlet IKScannerDeviceView *ScannerView;
-(void)scannerReopen;
#end
and:
#import "ScanWindowController.h"
#import "AppDelegate.h"
#interface ScanWindowController ()
#end
#implementation ScanWindowController
#synthesize ScannerView;
- (id)init
{
if ( ! (self = [super initWithWindowNibName: #"ScanWindowController"]) ) {
return nil;
}
if(!mDeviceBrowser) {
mDeviceBrowser = [[ICDeviceBrowser alloc] init];
[mDeviceBrowser setDelegate:self];
mDeviceBrowser.browsedDeviceTypeMask = ICDeviceLocationTypeMaskLocal|ICDeviceLocationTypeMaskRemote|ICDeviceTypeMaskScanner;
[mDeviceBrowser start];
}
return self;
}
- (void)windowDidLoad
{
[super windowDidLoad];
}
- (void)windowWillClose:(NSNotification *)notification {
[mDeviceBrowser stop];
}
- (void)scannerDeviceView:(IKScannerDeviceView *)scannerDeviceView didScanToURL:(NSURL *)url fileData:(NSData *)data error:(NSError *)error
{
//process the scanned data...
if(!error) {
[(AppDelegate*)[[NSApplication sharedApplication] delegate] receiveScannedData:data];
}
}
- (void)scannerDeviceDidBecomeAvailable:(ICScannerDevice*)scanner;
{
[scanner requestOpenSession];
}
- (void)deviceBrowser:(ICDeviceBrowser*)browser didAddDevice:(ICDevice*)addedDevice moreComing:(BOOL)moreComing
{
if ( (addedDevice.type & ICDeviceTypeMaskScanner) == ICDeviceTypeScanner )
{
[ScannerView setScannerDevice:(ICScannerDevice*)addedDevice];
}
}
-(void)deviceBrowser:(ICDeviceBrowser *)browser didRemoveDevice:(ICDevice *)device moreGoing:(BOOL)moreGoing
{
[device requestCloseSession];
}
-(void)didRemoveDevice:(ICDevice*)removedDevice
{
[removedDevice requestCloseSession];
}
-(void)scannerReopen
{
[mDeviceBrowser start];
}
#end

Navigation between NSVIewController

I am very new to MAC OSX app development.
In my application I have three NSViewControllers, which are PracticeController, NoteController and QuestionController. I have to navigate to NoteViewController from PracticeController and QuestionController and comeback to the viewController from which NoteController has navigated.
For example: when we navigate to NoteController from PracticeController, then when we tap on back button from NoteController I have to come to PracticeController, and when we navigate to NoteController from QuestionController, then when we tap on back button from NoteController I have to come to QuestionController.
Please help me how to do this? I am badly searching for it. Thanks.
well, after a long time search, I found a open source library which ports the UIKit to MacOSX.
https://github.com/BigZaphod/Chameleon.git
But it's too complicated for me, so I wrote my own Navigation controller.
NSNavigationController.h
#import <Cocoa/Cocoa.h>
#class BaseViewController;
#interface NSNavigationController : NSResponder
#property (nonatomic, strong) BaseViewController *rootViewController;
- (id)initWithRootViewController:(BaseViewController *)rootViewController;
- (NSView*)view;
- (void)pushViewController:(BaseViewController *)viewController animated:(BOOL)animated;
- (BaseViewController *)popViewControllerAnimated:(BOOL)animated;
#end
NSNavigationController.m
#import "NSNavigationController.h"
#import "AppDelegate.h"
#import "BaseViewController.h"
#interface NSNavigationController ()
#property (nonatomic, strong) NSMutableArray *viewControllerStack;
#end
#implementation NSNavigationController
- (id)initWithRootViewController:(BaseViewController *)rootViewController
{
self = [super init];
if (self) {
self.rootViewController = rootViewController;
self.rootViewController.navigationController = self;
self.viewControllerStack = [[NSMutableArray alloc] initWithObjects:self.rootViewController, nil];
}
return self;
}
- (NSView*)view
{
BaseViewController *topViewController = [self.viewControllerStack objectAtIndex:[self.viewControllerStack count] - 1];
return topViewController.view;
}
- (void)pushViewController:(BaseViewController *)viewController animated:(BOOL)animated
{
if (viewController != nil) {
[self removeTopView];
[self.viewControllerStack addObject:viewController];
viewController.navigationController = self;
[self addTopView];
}
}
- (BaseViewController *)popViewControllerAnimated:(BOOL)animated
{
BaseViewController *topViewController = [self.viewControllerStack objectAtIndex:[self.viewControllerStack count] - 1];
[self removeTopView];
[self.viewControllerStack removeLastObject];
[self addTopView];
return topViewController;
}
- (void)removeTopView
{
BaseViewController *topViewController = [self.viewControllerStack objectAtIndex:[self.viewControllerStack count] - 1];
[topViewController.view removeFromSuperview];
}
- (void)addTopView
{
BaseViewController *topViewController = [self.viewControllerStack objectAtIndex:[self.viewControllerStack count] - 1];
AppDelegate *delegate = (AppDelegate*)[NSApp delegate];
[delegate.window.contentView addSubview:topViewController.view];
}
#end
BaseViewController.h
#import <Cocoa/Cocoa.h>
#class NSNavigationController;
#interface BaseViewController : NSViewController
#property (nonatomic, weak) NSNavigationController *navigationController;
#end
BaseViewController.m
#import "BaseViewController.h"
#interface BaseViewController ()
#end
#implementation BaseViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Initialization code here.
}
return self;
}
#end
It's the simplest NavigationController. I didn't implement the view animation. Hope it can help.

Impossibility to show in a label the text of an object

My objective is to show in a label the text of an object of a custom class called Files. Here is Files.h :
#import <Foundation/Foundation.h>
#interface Files : NSObject
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) NSString *text;
#end
This is Files.m :
#import "Files.h"
#implementation Files
#dynamic title;
#dynamic text;
#end
Here is the .h file of my app. the label is called trackName:
#import <UIKit/UIKit.h>
#import "Files.h"
#interface FirstViewController : UIViewController
{
Files *plainpalais;
}
#property (weak, nonatomic) IBOutlet UILabel *trackName;
-(Files*) chooseFile;
#end
This is the .m file of the app:
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize trackName;
-(Files*)chooseFile
{
return plainpalais;
}
- (void)viewDidLoad
{
[super viewDidLoad];
plainpalais.text=#"hello";
plainpalais.title=#"plainpalais";
trackName.text=plainpalais.title;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setTrackName:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return YES;
}
}
#end
The problem is that the label trackName doesn't show plainpalais...
Thanks for help !
PS: I'm a beginner so this is probably a basic mistake.
You have used #dynamic in your Files.m implementation which tells the compiler that you'll provide getters/setters for these properties at a later time, i.e. using the Objective-C runtime.
I suspect you want to use #synthesize rather than #dynamic. For example,
#import "Files.h"
#implementation Files
#synthesize title;
#synthesize text;
#end
Also you haven't actually created a Files object in the code you have given us. The chooseFile method appears to be returning a nil object (assuming you haven't initialised plainpalais somewhere else). Perhaps you should initialise plainpalais in an init method, e.g.
- (id)init {
self = [super init];
if (self) {
plainpalias = [[Files alloc] init];
}
return self;
}
Don't forget to release this object in dealloc (if you aren't using ARC).

hide an object from another class

I'm trying to hide an object in my viewController, with code executed from a custom class, but the object is nil.
FirstViewController.h
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController {
IBOutlet UILabel *testLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *testLabel;
- (void) hideLabel;
FirstViewController.m
I synthesize testLabel and I have a function to hide it. If I call the function from viewDidAppear it works, but I want to call it from my other class. When called from the other class, testLabel is nil
#import "FirstViewController.h"
#import "OtherClass.h"
#implementation FirstViewController
#synthesize testLabel;
- (void) hideLabel {
self.testLabel.hidden=YES;
NSLog(#"nil %d",(testLabel==nil)); //here I get nil 1 when called from OtherClass
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
OtherClass *otherClass = [[OtherClass alloc] init];
[otherClass hideThem];
//[self hideLabel]; //this works, it gets hidden
}
OtherClass.h
#class FirstViewController;
#import <Foundation/Foundation.h>
#interface OtherClass : NSObject {
FirstViewController *firstViewController;
}
#property (nonatomic, retain) FirstViewController *firstViewController;
-(void)hideThem;
#end
OtherClass.m
calls the hideLabel function in FirstViewController. In my original project, (this is an example obviously, but the original project is at work) I download some data here and I want to hide my loading label and indicator when download is done
#import "OtherClass.h"
#import "FirstViewController.h"
#implementation OtherClass
#synthesize firstViewController;
-(void)hideThem {
firstViewController = [[FirstViewController alloc] init];
//[firstViewController.testLabel setHidden:YES]; //it doesn't work either
[firstViewController hideLabel];
}
Any ideas?
Your UILabel is nil because you just initialized your controller but didn't load it's view. Your controller`s IBoutlets are instantiated from the xib or storyboard automatically when you ask access to the bound view for the first time, so in order to access them you first have to load its view by some means.
EDIT (after OP comments):
Since your FirstViewController is already initialized and your OtherClass is instantiated by that controller, you could just hold a reference to it and not try to initialize a new one.
So try something like this:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
OtherClass *otherClass = [[OtherClass alloc] init];
otherClass.firstViewController = self;
[otherClass hideThem];
}
In your OtherClass.m:
-(void)hideThem {
[self.firstViewController hideLabel];
}

Cocoa Drag and Drop delegates not working the way I would expect

I made a very simple class that subclasses NSTextField so I could have more control over the drag and drop behavior, but I'm running into confusion. According to what I think I understand in the apple.developer docs on Dragging destinations, I should be able to get the delegates to fire when I enter or exit the bounds of the text field, but what I get instead is that the delegates don't fire until I have dropped something into the textField and then I try to drag it out.
I have a MyController class which is an NSObject and I have a CustomFields class of type NSTextField; There is nothing in the controller class.
Here is the code:
// CustomFields.h
// Drags
//
#import <AppKit/AppKit.h>
#import <Foundation/foundation.h>
#interface CustomFields : NSTextField{
NSString *tempStorage_;
unsigned long last_;
}
#property(readwrite, retain) NSString *tempStorage;
#end
//
// CustomFields.m
// Drags
//
#import "CustomFields.h"
#implementation CustomFields
#synthesize tempStorage = tempStorage_;
- (id)init{
if (self) {
self = [super init];
}
return self;
}
-(void)dealloc{
[self.tempStorage release ];
[super release];
}
-(void)awakeFromNib{
NSLog(#"Awake from nib called");
self.tempStorage = #"";
self->last_ = 0;
[self setBackgroundColor:[NSColor lightGrayColor]];
[self registerForDraggedTypes:[NSArray arrayWithObjects: NSPasteboardTypeString , NSPasteboardTypeString, nil]];
[super awakeFromNib];
}
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
NSLog(#"Inside dragging entered");
return NSDragOperationCopy;
}
- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
{
NSLog(#" draggingUpdated called");
return NSDragOperationCopy;
}
- (void)draggingExited:(id <NSDraggingInfo>)sender
{
NSLog(#"Inside dragging exited");
}
#end
//
// MyController.h
// Drags
//
#import <Foundation/Foundation.h>
#class CustomFields;
#interface MyController : NSObject{
IBOutlet NSButton *myButton_;
IBOutlet CustomFields *field1_;
IBOutlet CustomFields *field2_;
}
#end
//
// MyController.m
// Drags
//
#import "MyController.h"
#import "CustomFields.h"
#implementation MyController
#end
I made sure I assigned the correct class to the fields(CustomFields) in IB and connected them. As you can see, for the moment I would be happy to get log statements at the proper time. I also tried changing the MyController class to NSViewController and NSView so I could try registerForDraggedTypes there. That did'nt help anything and I don't think I should expect it to. I think the behaviors I want should be confined to the CustomFields Class which is one of the reasons the MyController class can be empty for the moment.
So any help is much apprecieted.

Resources