如何在 Objective-C 中将 NSView 转换为 NSTableView
How to convert NSView to NSTableView in Objective-C
我有一个 NSTableView,它有多个自定义 NSTableViewCell 对象。
每个 NSTableViewCell 对象都有三个 NSTextField。
我想在每个 NSFields 中发送输入的文本并将其分配给一个 String 变量。
问题是我需要获取超级视图对象才能确定自定义 NSTableViewCell 所在的 selectedRow。
在 Swift 中可能看起来像这样:
let textField = sender as! NStextField
let myView = textField.superview?.superview?.superview as! NSTableView
let num = myView.row(for: textField.superview!)
我对其中一个 NSTextField 进行了尝试:
- (IBAction)setValue:(id)sender {
NSTableView *thisTable = self.cell.superview.superview.superview.superview;
NSInteger num = [thisTable selectedRow];
}
它没有用,而且我收到了这个警告:
Incompatible pointer types initializing 'NSTableView *' with an
expression of type 'NSView * _Nullable'
我的 CustomCell class 是一个简单的 Class 只是为了绘制单元格。
@implementation CustomCell
- (id)init {
self = [super init];
if(self != nil) {
_cellTitle;
_cellBackLight;
_cellTime;
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
}
.h 文件:
@interface CustomCell : NSTableCellView
@property NSString *cellTitle;
@property double cellValue;
@property int cellTime;
@property (strong) IBOutlet NSTextField *titleField;
@property (strong) IBOutlet NSTextField *valueField;
@property (strong) IBOutlet NSTextField *durationField;
//All outlets are linked from Storyboard to the CustomCell class.
@end
tableView 委托:
- (id)tableView:(NSTableView *)viewTableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)rowIndex {
NSTableCellView *cell = [viewTableView makeViewWithIdentifier:tableColumn.identifier owner:self];
cell = [viewTableView makeViewWithIdentifier:@"MainCell" owner:self];
return cell;
}
我想要达到的目标:
完全忘记了 Objective C
的语法,但这是在 Swift
中为 iOS 实现的方法。
免责声明: 我很清楚 iOS 和 MacOS 开发之间存在许多差异,但这是 "how to organise your code to achieve this specific task" 上的展示。即使不是copy/pastable,甚至没有测试,采用的方法都是一样的。
假设您有 class Person
:
class Person {
var title: String = ""
var name: String = ""
var surname: String = ""
}
您可以在 ViewController 中添加一个 Person
的数组。
该数组绑定到您的 tableView 数据源,因此其中的 Person
个实例显示在您的 TableView
中
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var personArray: [Person] = []
// MARK:- TableViewDelegate
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return personArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifier", for: indexPath) as! CustomCell
cell.person = personArray[indexPath.row] // - 1
return cell
}
}
正如您所注意到的,该单元格现在包含一个新的引用 person
到您想要 display/edit 的关联人。
请参阅下面的 CustomCell
实施:
class CustomCell: UITableViewCell, UITextFieldDelegate {
weak var person: Person? { // the reference to the associated person
didSet {
// when Person is set, we update the fields
titleTextField.text = person?.title ?? ""
nameTextField.text = person?.name ?? ""
surnameTextField.text = person?.surname ?? ""
}
}
@IBOutlet weak var titleTextField: UITextField!
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var surnameTextField: UITextField!
override func awakeFromNib() {
super.awakeFromNib()
// Add action when textField text change
titleTextField.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: .editingChanged)
nameTextField.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: .editingChanged)
surnameTextField.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: .editingChanged)
}
@objc func textFieldDidChange(textField: UITextField){
// switch on the textField to see which info should be edited
switch textField {
case titleTextField:
person?.title = titleTextField.text ?? ""
case nameTextField:
person?.name = nameTextField.text ?? ""
case surnameTextField:
person?.surname = surnameTextField.text ?? ""
default: break
}
}
}
这样做,您对 Person
的修改将在关联的 CustomCell
中处理。
重新加载 tableview 时,它将保留您已输入的数据
当您编辑 TextField 时,它会更改 person
并且考虑到它是一个参考,您会在主要 VC
上看到 personArray
的差异
再说一次,它不是 copy/pastable,应该被视为 pseudo-code
仅供参考,我发现了如何在自定义单元格中获取所选行 table 视图:
- (IBAction)name:(id)sender {
NSInteger num = [_viewTableView selectedRow];
NSLog(@"thisTable selectedRow %ld", (long)num);
}
我有一个 NSTableView,它有多个自定义 NSTableViewCell 对象。 每个 NSTableViewCell 对象都有三个 NSTextField。 我想在每个 NSFields 中发送输入的文本并将其分配给一个 String 变量。 问题是我需要获取超级视图对象才能确定自定义 NSTableViewCell 所在的 selectedRow。
在 Swift 中可能看起来像这样:
let textField = sender as! NStextField
let myView = textField.superview?.superview?.superview as! NSTableView
let num = myView.row(for: textField.superview!)
我对其中一个 NSTextField 进行了尝试:
- (IBAction)setValue:(id)sender {
NSTableView *thisTable = self.cell.superview.superview.superview.superview;
NSInteger num = [thisTable selectedRow];
}
它没有用,而且我收到了这个警告:
Incompatible pointer types initializing 'NSTableView *' with an expression of type 'NSView * _Nullable'
我的 CustomCell class 是一个简单的 Class 只是为了绘制单元格。
@implementation CustomCell
- (id)init {
self = [super init];
if(self != nil) {
_cellTitle;
_cellBackLight;
_cellTime;
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
}
.h 文件:
@interface CustomCell : NSTableCellView
@property NSString *cellTitle;
@property double cellValue;
@property int cellTime;
@property (strong) IBOutlet NSTextField *titleField;
@property (strong) IBOutlet NSTextField *valueField;
@property (strong) IBOutlet NSTextField *durationField;
//All outlets are linked from Storyboard to the CustomCell class.
@end
tableView 委托:
- (id)tableView:(NSTableView *)viewTableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)rowIndex {
NSTableCellView *cell = [viewTableView makeViewWithIdentifier:tableColumn.identifier owner:self];
cell = [viewTableView makeViewWithIdentifier:@"MainCell" owner:self];
return cell;
}
我想要达到的目标:
完全忘记了 Objective C
的语法,但这是在 Swift
中为 iOS 实现的方法。
免责声明: 我很清楚 iOS 和 MacOS 开发之间存在许多差异,但这是 "how to organise your code to achieve this specific task" 上的展示。即使不是copy/pastable,甚至没有测试,采用的方法都是一样的。
假设您有 class Person
:
class Person {
var title: String = ""
var name: String = ""
var surname: String = ""
}
您可以在 ViewController 中添加一个 Person
的数组。
该数组绑定到您的 tableView 数据源,因此其中的 Person
个实例显示在您的 TableView
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var personArray: [Person] = []
// MARK:- TableViewDelegate
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return personArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifier", for: indexPath) as! CustomCell
cell.person = personArray[indexPath.row] // - 1
return cell
}
}
正如您所注意到的,该单元格现在包含一个新的引用 person
到您想要 display/edit 的关联人。
请参阅下面的 CustomCell
实施:
class CustomCell: UITableViewCell, UITextFieldDelegate {
weak var person: Person? { // the reference to the associated person
didSet {
// when Person is set, we update the fields
titleTextField.text = person?.title ?? ""
nameTextField.text = person?.name ?? ""
surnameTextField.text = person?.surname ?? ""
}
}
@IBOutlet weak var titleTextField: UITextField!
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var surnameTextField: UITextField!
override func awakeFromNib() {
super.awakeFromNib()
// Add action when textField text change
titleTextField.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: .editingChanged)
nameTextField.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: .editingChanged)
surnameTextField.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: .editingChanged)
}
@objc func textFieldDidChange(textField: UITextField){
// switch on the textField to see which info should be edited
switch textField {
case titleTextField:
person?.title = titleTextField.text ?? ""
case nameTextField:
person?.name = nameTextField.text ?? ""
case surnameTextField:
person?.surname = surnameTextField.text ?? ""
default: break
}
}
}
这样做,您对 Person
的修改将在关联的 CustomCell
中处理。
重新加载 tableview 时,它将保留您已输入的数据
当您编辑 TextField 时,它会更改 person
并且考虑到它是一个参考,您会在主要 VC
personArray
的差异
再说一次,它不是 copy/pastable,应该被视为 pseudo-code
仅供参考,我发现了如何在自定义单元格中获取所选行 table 视图:
- (IBAction)name:(id)sender {
NSInteger num = [_viewTableView selectedRow];
NSLog(@"thisTable selectedRow %ld", (long)num);
}