0

I am working on this couple of days and I can't figure out what I am doing wrong.

First, I don't know if the KVO is the best way to pass the value of the clicked row info from one view controller to another view controller.

I have Main view, with 2 buttons only. Clicking on one of the buttons, I open MasterTableViewController, where I have the NSTableView with some records (one column only) from core data.

On click on the NSTableView, I am opening the DetailViewController, where I have only one label.

What I am trying is to change the label value, with the value of the clicked row in the NSTableView.

While I can print the value of the clicked row in the DetailViewController, I can't change the label value. I assume that notification comes before the viewDidLoad get called.

I have the following code:

In my MasterTableViewController.h file:

#import <Cocoa/Cocoa.h>
#import "AppDelegate.h"

@interface MasterTableViewController : NSViewController

@property (nonatomic,strong) NSManagedObjectContext *mObjContext;
@property (weak) IBOutlet NSTableView *websitesTableView;
- (IBAction)tableViewDoubleClick:(id)sender;

@property (nonatomic,strong) NSString *cellValue;
@end

In my MasterTableViewController.m file:

#import "MasterTableViewController.h"
#import "DetailViewController.h"
@interface MasterTableViewController ()

@end

@implementation MasterTableViewController

-(void)awakeFromNib {
    [_websitesTableView setTarget:self];
    [_websitesTableView setDoubleAction:@selector(tableViewDoubleClick:)];
}



- (void)viewDidLoad {
    [super viewDidLoad];
    // Get the object managed context
    AppDelegate *appDelegate = (AppDelegate*)[[NSApplication sharedApplication] delegate];
    self.mObjContext = appDelegate.managedObjectContext;

}


- (IBAction)tableViewDoubleClick:(id)sender {   
    NSInteger rowNumber = [_websitesTableView clickedRow];
    NSTableColumn *column = [_websitesTableView tableColumnWithIdentifier:@"websiteUrl"];
    NSCell *cell = [column dataCellForRow:rowNumber];

    _cellValue = [cell stringValue];

    MasterTableViewController *mtvc = [[MasterTableViewController alloc]initWithNibName:@"MasterTableViewController" bundle:nil];
    DetailViewController *dvc = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];


    [mtvc addObserver:dvc
           forKeyPath:@"cellValue"
              options:NSKeyValueObservingOptionNew
              context:NULL];

    [mtvc setCellValue:_cellValue];
    [mtvc removeObserver:dvc forKeyPath:@"cellValue"];


    AppDelegate *appDelegate = (AppDelegate*)[[NSApplication sharedApplication] delegate];
    [appDelegate changeViewController:2];
}

@end

Code for the DetailViewController.h is:

#import <Cocoa/Cocoa.h>
#import "AppDelegate.h"
@interface DetailViewController : NSViewController
@property (nonatomic, weak) AppDelegate *appDelegate;
@property (weak) IBOutlet NSTextField *detailLabel;
@property (nonatomic,strong) NSString *transferedLabelValue;
@property (nonatomic,strong) NSString *cellValue;

@end

Code for the DetailViewController.m is:

#import "DetailViewController.h"
#import "MasterTableViewController.h"
@interface DetailViewController ()

@end

@implementation DetailViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // if I uncomment this line, program crashes, because the value of the _transferedLabelValue is null here.
    //[_detailLabel setStringValue:_transferedLabelValue];

}

-(void)observeValueForKeyPath:(NSString *)keyPath
                 ofObject:(id)object
                   change:(NSDictionary *)change
                  context:(void *)context {
if ([keyPath isEqualToString:@"cellValue"]) {

    _transferedLabelValue = [change objectForKey:NSKeyValueChangeNewKey];
    // Here I get the value of the clicked cell, it is printed in the console. However if I try to change the label value here, doesn't work, since seems that label does not exist yet at this point....
    NSLog(@"Value in the observerValueForKeyPath is:%@",_transferedLabelValue);
}

}

@end

Code from the 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 (weak) IBOutlet NSView *mainAppView;
@property (nonatomic,strong) NSViewController *mainAppViewController;

- (IBAction)showMasterViewButtonHasBeenClicked:(id)sender;
- (IBAction)showDetailViewButtonHasBeenClicked:(id)sender;
- (void)changeViewController:(NSInteger)tag;

@end

Here is only the relevant code from the AppDelegatge.m, the boiler plate code is omited.

#import "AppDelegate.h"
#import "MasterTableViewController.h"
#import "DetailViewController.h"

@interface AppDelegate ()

@property (weak) IBOutlet NSWindow *window;
- (IBAction)saveAction:(id)sender;

@end

@implementation AppDelegate

- (IBAction)showMasterViewButtonHasBeenClicked:(id)sender {
    NSInteger tag = [sender tag];
    [self changeViewController:tag];
}

- (IBAction)showDetailViewButtonHasBeenClicked:(id)sender {
    NSInteger tag = [sender tag];
    [self changeViewController:tag];
}

- (void)changeViewController:(NSInteger)tag {
    [[_mainAppViewController view]removeFromSuperview];

    switch (tag) {
        case 1:

            self.mainAppViewController = [[MasterTableViewController alloc]initWithNibName:@"MasterTableViewController" bundle:nil];
            [_mainAppView addSubview:[_mainAppViewController view]];
            [[_mainAppViewController view] setFrame:[_mainAppView bounds]];
            [[_mainAppViewController view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
            break;

        case 2:

            self.mainAppViewController = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];
            [_mainAppView addSubview:[_mainAppViewController view]];
            [[_mainAppViewController view] setFrame:[_mainAppView bounds]];
            [[_mainAppViewController view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];

            break;

    }

}

Again, if the KVO and notification is not the best way to go, please let me know how I should "inform" the other view which row has been clicked and which is his value.

Regards, John

user2417624
  • 653
  • 10
  • 32
  • 1
    what is `_detailLabel ` . And please `NSLog(@"_detailLabelNewValue: %@",_detailLabelNewValue)` – tuledev Aug 22 '15 at 03:45
  • For that matter, do `NSLog(@"_detailLabel %@", _detailLabel)`, too. – Ken Thomases Aug 22 '15 at 04:36
  • _detailLabel is an outlet to the label that I am trying to change the value. _detailLabelNewValue is a property that I am using to keep the value of the notification. – user2417624 Aug 22 '15 at 08:28
  • [_detailLabel setStringValue:_detailLabelNewValue]; NSLog(@"_detailLabelNewValue: %@",_detailLabelNewValue); NSLog(@"_detailLabel: %@",_detailLabel); ****** _detailLabelNewValue returns value, while _detailLabel is null – user2417624 Aug 22 '15 at 09:40

1 Answers1

2

I manage to solve my problem with the KVO...My problem was that I was creating new instances of the view controllers in the MasterTableViewController...What I did was I created properties for the ViewControllers in the appDelegatge.h like this:

@property MasterTableViewController *mtvc;
@property DetailViewController *dvc;

and then in the appDelegate.m :

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
   _mtvc = [[MasterTableViewController alloc]initWithNibName:@"MasterTableViewController" bundle:nil];
   _dvc = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];
}

Rest of the changes in the code are just replacing the MasterTableViewController and DetailViewController with _mtvc and _dvc...

However...I had been warned that this solution is error prone, and that warning shows true. It happens from time to time that I get wrong value, not the clicked one. Once in 4-5 clicks, I get wrong value. What makes me confuse is that I make the function to work on double click, but it works on single click as well...But those things are for some other question I guess.

user2417624
  • 653
  • 10
  • 32