5

10.8で実行されているビューベースのNSTableViewで問題が発生しています(ターゲットは10.7ですが、これは関係ないと思います)。

NSTableViewを使用しており、バインディングを介してカスタムNSTableCellViewのコンテンツ値を取得しています。NSTableCellViewのobejctValueを使用してデータを取得します。

セルにボタンを追加しました。クリックするとアクションがトリガーされるようにします。これまでのところ、カスタムNSTableCellViewのサブクラス内でのみアクションをトリガーできました。

チェーンを使用して、次のようにクリックされた行を取得できます。

NSButton *myButton = (NSButton*)sender;    

NSTableView *myView = (NSTableView*)myButton.superview.superview.superview;

NSInteger rowClicked = [myView rowForView:myButton.superview];

そこから、アクションが定義されているAppDelegateまたはコントローラーに到達する方法がわかりません。

ココアバインディングを使用しているため、アクションをトリガーするために使用できるデリゲートがNSTableViewにありません。

どうすればコントローラーに話しかけることができるかわかりますか?

よろしくお願いします!

4

4 に答える 4

3

ご質問ありがとうございます。NSTableViewのボタンからもアクションをトリガーします。あなたの質問は私を正しい道に導くのに役立ちました。

最初に、NSTableViewがオンになっている行番号を見つけるためのソリューションに取り組みます。ボタンを知らなくても見つけることができました。カスタムNSTableViewに、最初の試みとして次のものをインストールしました。

- (NSInteger)myRowNumber  
{  
    return [(NSTableView*)self.superview.superview rowForView:self];  
}

これは正常に機能しますが、堅牢ではありません。これは、ビュー階層の深さを具体的に知っている場合にのみ機能します。より堅牢で普遍的なソリューションは次のとおりです。

- (NSInteger)myRowNumber  
{   
    NSTableView* tableView = nil;   
    NSView* mySuperview = self;   

    do   
    {   
        NSView* nextSuper = mySuperview.superview;   
        if (nextSuper == nil)   
        {   
            NSException *exception =   
                [NSException exceptionWithName:@"NSTableView not found."   
                    reason:[NSString stringWithFormat:@"%@ search went too deep.",   
                    NSStringFromSelector(_cmd)] userInfo:nil];   
            @throw exception;   
        }   

        if ([nextSuper isKindOfClass:[NSTableView class]])   
            tableView = (NSTableView*)nextSuper;   
        else   
            mySuperview = mySuperview.superview;   
    } while (tableView == nil);   

    return [tableView rowForView:self];   
}   

これは、NSTableViewレベルで機能するだけでなく、ビュー階層がどれほど複雑であっても、その上の任意のレベルにインストールされているものすべてで機能します。

あなたの質問の未回答の部分に関しては、私はクラスにIBOutletを確立し、ファイル所有者(私の場合はドキュメントクラス)に関連付けられたインターフェイスビルダーを使用しました。メッセージの送信先のクラスと行番号への参照を取得したら、関数を呼び出します。私の場合、呼び出しでは、発信元の行番号を渡す必要がありました。

[self.myDoc doSomethingToRow:self.myRowNumber];   

これをテストしたところ、NSTableViewの上のビュー階層のさまざまなレベルで機能します。また、最初に行を選択しなくても機能します(これは、Appleのドキュメントで想定されているようです)。

よろしく、ジョージローレンスストーム、モルトビー、ワシントン、米国

于 2013-01-10T12:53:49.487 に答える
3

バインディングを使用している場合でも、InterfaceBuilderでテーブルビューのデリゲートとしてコントローラーを設定できます。

セル内からテーブルビューにアクセスできるようになっているようです。次のタスクは単純である必要があります。ボタンのアクションのターゲットとしてテーブルビューデリゲートを設定するだけです。

于 2012-09-05T03:36:13.713 に答える
2

使用rowForView:とレスポンダーチェーン

に埋め込まれたコントロールのアクションに応答するには、コントロールはファーストレスポンダーNSTableCellViewにアクションを発行する必要があります。または、ファイル所有者も可能ですが、これはより緊密に結合されています。

rowForView:アクションメソッド内で使用して、アクションを発行した行のコントロールを判別します。

- (IBAction)revealInFinder:(id)sender {
    NSInteger row = [self.tableView rowForView:sender];
    ...
}

アクションは、任意のレスポンダーチェーンクラス内に実装されます。ほとんどの場合、これはサブクラス化されNSWindowControllerたインスタンスになります。レスポンダーは、アプリケーションの代理人になることもできます。代理人がと話す手段を持っていると仮定しNSTableViewます。

これが実際に動作していることを確認するには、 AppleのサンプルTableViewPlayground:ビューベースのNSTableViewおよびNSOutlineViewの使用を参照してください。

于 2017-11-30T11:18:09.120 に答える
0

スハスの答えは私を助けました。

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {

    if let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "EDIT_CELL_VIEW"), owner: self) as? SymbolManagerCell  {                    
                if let editButton = cell.subviews[0] as? NSButton {
                    editButton.target = cell // this is required to trigger action
                }
                return cell
            }
    return nil
}
于 2019-03-04T18:12:06.270 に答える