简体   繁体   中英

How to change selection of NSMatrix in IBAction?

I have NSRadioModeMatrix with 3 cells. - (IBAction) EnableProxy:(id)inSender is connected to NSRadioModeMatrix

- (IBAction) EnableProxy:(id)sender
{   

    if ([[sender selectedCell] tag]==2)
    { 

/*(gdb) p (int)[[inSender selectedCell] tag]
$1 = 2*/
        if (condition) {
             // select cell with tag 0
            [sender selectCellAtRow:0 column:0]; // This is not working
        }
        /*(gdb) p (int)[[inSender selectedCell] tag]
$2 = 1*/
    }
}// selection is not visible

When condition is true. selection is going back to tag 2(old selected cell). Sample project .

To be honest, this is the intended behavior, and for good reason.

在此输入图像描述

Given the above UI, if a user clicks on C , they expect C to become selected. If instead, a user clicks on C and A becomes selected, you have a confused (and potentially frustrated) user. Indeed, implementing this type of behavior violates the OS X Human Interface Guidelines for Radio Buttons .

That said, I'll move on to how you can implement the behavior you want. Basically, the reason why when you select C , the immediate call to select A doesn't seem to succeed is that, technically speaking, C is still in the process of being selected. In other words, a simplified timeline of the events would look like the following:

  1. begin click on matrix
  2. EnableProxy: method called
  3. matrix immediately told to select A
  4. finished click on matrix and C is finally completely selected

In order to achieve the results you want, instead of immediately telling the matrix to select A , you'll need to "queue" the request up like the following code does:

- (IBAction) EnableProxy:(id)inSender {
    if ([[inSender selectedCell] tag] == 2) {
//        [mProxyEnable selectCellAtRow:0 column:0];
        [self performSelector:@selector(selectFirstMatrixRow) withObject:nil
                                                              afterDelay:0.0];
    }
}

- (void)selectFirstMatrixRow {
    NSLog(@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
    [mProxyEnable selectCellAtRow:0 column:0];
}

By using [self performSelector:withObject:afterDelay:] , you basically say "call this method as soon as possible". Doing so lets C be fully selected before that method is called, which allows the results you want. In other words, the timeline of events would look like this:

  1. begin click on matrix
  2. EnableProxy: method called
  3. finished click on matrix and C is finally completely selected
  4. --------- control returns to normal event loop ---------
  5. selectFirstMatrixRow method called
  6. matrix selects A

With reference to the above answer provided by NSGod, This can be also achieved using GCD rather giving the unnecessary delay with 0.0

ViewController * __weak weakRef = self;
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakRef selectFirstMatrixRow];
        });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM