Multiple NSPopover ecrasing each other - objective-c

I'm trying to put two NSPopover on two Help Buttons on a .xib file.
To do so, I declared in my .h
#interface ExportPreferences : NSPreferencePane <NSPopoverDelegate>
{
NSWindow *window;
NSPopover *popover;
NSUserDefaults *prefs;
NSMutableArray *myArran;
IBOutlet NSButton *images;
IBOutlet NSPopUpButton *modalities;
IBOutlet NSPathControl *path;
IBOutlet NSPopUpButton *tree;
IBOutlet NSPopUpButton *extension;
}
#property (assign) IBOutlet NSWindow *window;
#property (assign) IBOutlet NSPopover *popover;
#end
And two different methods in my .m :
- (IBAction) showInfoTreePopover {
[[self popover] showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMaxXEdge];
}
- (IBAction) showInfoTypePopover {
[[self popover] showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMaxXEdge];
}
Then, in my .xib I declared
A Popover with its Popover View Controller
A Custom View
A Label (on the CV)
And I linked :
The Help Button to its corresponding method (one for the Tree, one for the Type)
The File's Owner to the Popover
The Popover View Controller to the Custom View
Since I do have two NSPopover to implement, I did all of this twice, two Popover, two Popover View Controller, two Custom View, two labels.
When I compile, everything goes right, but when I test it, it appears that only my second Popover shows up on the two buttons. It seems that implementing the second Popover, erased the first one.
how may I patch that ?

Alright, I answered my own question but I think I might give the answer if anyone faces the same problem.
When using two NSPopovers, I had to declare two different Outlets,
NSPopover *treePopover;
NSPopover *typePopover;
Also, two properties
#property (assign) IBOutlet NSPopover *treePopover;
#property (assign) IBOutlet NSPopover *typePopover;
And now, the linking works perfectly.

Related

NSWindow update content when show/hide

I have added NSWindow element in my.xib file and inserted some element to it, such as imageView. And then created class of type NSWindow named customNSWindow and assign these class to the xib element which I have created(NSWindow). Now from another WindowController I need to show/hide the customNSWindow. This is done by putting an outlet to the WindowController.
viewController.h
#property (strong) IBOutlet NSWindow *ImageEditWindow;//(custom window)
viewController.mm
-(IBAction)ButtonClick:(id)sender {
if(! [_ImageEditWindow isVisible] ){
[_ImageEditWindow makeKeyAndOrderFront:sender];
}
}
But I don't know I how to update image in ImageEditWindow, I cannot find way to call a method inside the custom class I created, using _ImageEditWindow outlet.
Edit
Here is the custom class for NSWindow
CustomIKImageEditor.h
#interface CustomIKImageEditor : NSWindow
#property (weak) IBOutlet IKImageView *IKImg;
-(void) updateIKImage: (NSImage*)staticImageToEdit;
#end
CustomIKImageEditor.mm
-(void) updateIKImage: (NSImage*)staticImageToEdit {
NSDictionary* _imageProperties;
CGImageRef source = [self CGImageCreateWithNSImage: staticImageToEdit];
_imageProperties = NULL;
[_IKImg setImage: source imageProperties: NULL];
}
This line:
#property (strong) IBOutlet NSWindow *ImageEditWindow;//(custom window)
Should be:
#property (strong) IBOutlet CustomIKImageEditor *ImageEditWindow;//(custom window)

Double click on row in NSTableView doesn't display the new view

I have an os x app that uses core data.
I have 3 .xib files in my app, those are:
1. MainMenu.xib
2. MasterTableViewController.xib
3. DetailViewController.xib
When started , app displays a view that has NSTableView with couple of records in it.
I name that view MasterTableViewController
I want when user double click on the row, to hide the "master" view and to display my "detail" view. I named that view DetailViewController.
When double clicked on the row in the NSTableView in the "master" view,nothing happen, "master" view remains visible. What I want is "master" view to dissapear, and "detail" view to appear.
Here is the code that I have right now, and more explanations follows:
AppDelegate.h
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (nonatomic,strong) NSViewController *mainAppViewController;
#property (weak) IBOutlet NSView *mainAppView;
- (void)changeViewController:(NSInteger)tag;
#property (weak) IBOutlet NSTableView *websitesTableView;
- (void)tableViewDoubleClick:(id)nid;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "MasterTableViewController.h"
#import "DetailViewController.h"
#interface AppDelegate ()
#property (weak) IBOutlet NSWindow *window;
- (IBAction)saveAction:(id)sender;
#end
#implementation AppDelegate
NSString *const masterTable = #"MasterTableViewController";
NSString *const detail = #"DetailViewController";
-(void)awakeFromNib {
[_websitesTableView setTarget:self];
[_websitesTableView setDoubleAction:#selector(tableViewDoubleClick:)];
}
- (void)tableViewDoubleClick:(id)nid {
NSInteger rowNumber = [_websitesTableView clickedRow];
NSTableColumn *column = [_websitesTableView tableColumnWithIdentifier:#"websiteUrl"];
NSCell *cell = [column dataCellForRow:rowNumber];
NSInteger tag = 2;
[self changeViewController:tag];
}
- (void)changeViewController:(NSInteger)tag {
[[_mainAppViewController view]removeFromSuperview];
switch (tag) {
case 1:
self.mainAppViewController = [[MasterTableViewController alloc]initWithNibName:masterTable bundle:nil];
break;
case 2:
self.mainAppViewController = [[DetailViewController alloc]initWithNibName:detail bundle:nil];
break;
}
[_mainAppView addSubview:[_mainAppViewController view]];
[[_mainAppViewController view] setFrame:[_mainAppView bounds]];
[[_mainAppViewController view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// automatically run the master table view controller
NSInteger tag = 1;
[self changeViewController:tag];
}
Now, some of you may wondering, where is the rest of the code. I have ommited the boiler plate code for the core data below in the AppDelegage.m, since it is unchanged. I used binding to make my NSTableView to work and to display my records, so MasterTableViewController.h and .m files are empty, and same is true for the DetailViewController.h and .m file.
Important note - What i can't understand here: If I change the tag in 2 in the applicationDidFinishLaunching method, detail view is displayed normally, but if i switch it back on 1, and then double click on the row, "master" view (with the NSTableView) remains visible, and nothing happen (views are not swapped)
Anyone can help me to find out what is wrong with my code?
Regards, John
You apparently had a second instance of your AppDelegate class instantiated in the MasterTableViewController.xib file. There should be only one AppDelegate instance and that's the one in MainMenu.xib. So, it shouldn't be in MasterTableViewController.xib.
One of the instances was receiving the double-click action method from the table, but the other one was the one with the outlet to the main window.
You need(ed) to get rid of the second instance and find another way to access the app delegate from the MasterTableViewController.

Root View Controller's child View Controllers are on top of root

I have what is a seemingly simple problem but I cannot find a solution! I have a subclass of UIViewController that is my root view controller, and ten different other UIViewcontrollers that I want to load in as child view controllers when called (one at a time, not all ten on screen at once.)
The root controller has a few buttons whose actions call the respective code to bring up a child view controller. The root view controller is loaded first by the nib and I want to instantiate it with page01ViewController as the first child. But whenever I call the following code, the child view controller is overlayed on top of my rootViewController, hiding all of the control buttons in my root controller!
// RDJrootPageViewController.m
#import "RDJrootPageViewController.h"
#import "RDJhomeScreenViewController.h"
#import "RDJpage01ViewController.h"
#import "RDJpage02ViewController.h"
#import "RDJpage03ViewController.h"
#import "RDJpage04ViewController.h"
#import "RDJpage05ViewController.h"
#import "RDJpage06ViewController.h"
#import "RDJpage07ViewController.h"
#import "RDJpage08ViewController.h"
#import "RDJpage09ViewController.h"
#import "RDJpage10ViewController.h"
#interface RDJrootPageViewController ()
#property (retain, nonatomic) RDJhomeScreenViewController *homeScreenViewController;
#property (retain, nonatomic) RDJpage01ViewController *page01ViewController;
#property (retain, nonatomic) RDJpage02ViewController *page02ViewController;
#property (retain, nonatomic) RDJpage03ViewController *page03ViewController;
#property (retain, nonatomic) RDJpage04ViewController *page04ViewController;
#property (retain, nonatomic) RDJpage05ViewController *page05ViewController;
#property (retain, nonatomic) RDJpage06ViewController *page06ViewController;
#property (retain, nonatomic) RDJpage07ViewController *page07ViewController;
#property (retain, nonatomic) RDJpage08ViewController *page08ViewController;
#property (retain, nonatomic) RDJpage09ViewController *page09ViewController;
#property (retain, nonatomic) RDJpage10ViewController *page10ViewController;
#end
#implementation RDJrootPageViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
currentPage = 1;
self.page01ViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"page01"];
[_page01ViewController.view setFrame:CGRectMake(0, 0, 1024, 768)];
[self addChildViewController:_page01ViewController];
[self.view addSubview:_page01ViewController.view];
[_page01ViewController didMoveToParentViewController:self];
[self.view setUserInteractionEnabled:YES];
}
My problem is similar to the one asked here, but no solution was ever identified:
Return from Child View Controller to Container
Every tutorial I find has the same setup: make your new VC, add it as a childView to self, then add that as a subview to your root view, but it dosen't work.
Anyone know the right way to do this?
You may want to user insertSubview:atIndex:. Using an index of 0 will add the view under all the other views. Alternatively you could have a container view for the views of the page view controllers. This container view needs to be added at index 0 in the view of RDJrootPageViewController. The page view controllers views could be added to the afore mentioned container view.
Hope this helps.

Access a UITextField in another UIViewControllers view

This is how I use a XIB view controllers view as a subview in the MainViewController:
UIViewController *nameController = [[NameSubViewController alloc] initWithNibName:#"NameSubViewController" bundle:nil];
nameSubView = [nameController view];
[self.view addSubview:nameSubView];
The nameController view contains a UITextField property. Can I somehow access this property from MainViewController?
EDIT:
If I create a property for the textField in the View Controller too, I'm still not able to get it in MainViewController. Think it's because of the UIView subclassed causing problems?
NameSubViewController.h:
#import <UIKit/UIKit.h>
#interface NameSubViewController : UIViewController
#property (nonatomic, strong) IBOutlet UITextField *textField;
#end
NameSubView.h:
#import <UIKit/UIKit.h>
#interface NameSubView : UIView
#property (nonatomic, strong) IBOutlet UITextField *textField;
- (IBAction)textFieldReturn:(id)sender;
#end
Connections in IB for NameSubViewController:
Connections, NameSubViewController
Connections in IB for NameSubView:
Connections, NameSubView
Did you create an outlet for the textfield in your nameController? Do that, and then you can retrieve the value using
nameController.textField.text
In the nib file, click on the file's owner icon (on the left of the nib), and set it's class to your UIView's subclass using the inspector on the right.
Why are you adding view from Controller A in Controller B. Isn't it better that you create a view by only using its xib file and add that view to your controllers view.
For accessing field, you can assign a tag to your textfield, and where ever in your code you need it, call
self.view viewWithTag:<#(NSInteger)#> method.

Correct way of setting up UINavigationController and its RootViewController in IB

I have the following structure in my iPad App:
Application
UINavigationController (Providing the top bar with UIBarButtons etc.)
Initial Login screen
Second login screen
I am not sure how I should now set this up in Interfacebuilder correctly. My guess would be that I create two ViewControllers:
LoginVC1: (This one should also include the NavigationController since it is the first of the two screens)
LoginVC2: Based on some delegate callback from LoginVC1 my application would push to this ViewController.
This is my LoginVC1 in IB:
LoginVC1 http://k.minus.com/jpamEAFkBjpKT.png
And when I present it modally it looks like this which is not what I want:
Result http://k.minus.com/jHAYRnY788jFt.png
The result:
Nor the title of the ViewController nor the Cancel button is shown
The view seems to be empty despite my view in IB
I have set the Presentation mode of the UINavigationController to FormSheet which is ignored too since it is displayed in fullscreen.
What am I doing wrong?
Kjuly I simply do presentModalViewController to show the dialog, but
since my UINavigationControler contains a UIViewController (See
nib-screen), I would assume that this ViewController is displayed when
the modal is shown.
Not always Besi. Adding it to the UINavigationController Hierarchy doesn't add is as the rootViewController. That must be done in code like this:
UIViewController *rootViewController = [[[ExamplesViewController alloc] init] autorelease];
UINavigationController * navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
Also, check that you are presenting the NavigationController, and not the ViewController modally.
To solve the NavigationBar title issue, try setting the self.title property in the
-(void)viewDidload method and see if that works. If not, try self.//instance of UINavigationController//.navigationBar.title = #"string".
As for the other buttons not showing up, my guess is that if setting the root controller in code doesn't help, then you only made reference to them in the .h, instead of instantiating them. So either call something like this in the .h:
//.h
#implementation ExampleViewController: UIViewController <UITextFieldDelegate> {
IBOutlet UIBarButtonItem * CancelButton;
IBOutlet UITextField * usernameField;
IBOutlet UITextField * passwordField;
IBOutlet UIButton * loginButton;
}
#property (nonatomic, retain) IBOutlet UIBarButtonItem * CancelButton;
#property (nonatomic, retain) IBOutlet UITextField * usernameField;
#property (nonatomic, retain) IBOutlet UITextField * passwordField;
#property (nonatomic, retain) IBOutlet UIButton * loginButton;
Then connect the outlets in the XIB, or instantiate the buttons in the .m with:
//.m
-(void)viewDidLoad {
//do stuff
CancelButton = [[[UIBarButtonItem alloc]initWithTitle:#"Cancel" style:UIBarButtonItemStyleDone target:self action:#selector(dismissSelf)]autorelease];
//do more stuff
}