diff --git a/redo/objc_darwin.h b/redo/objc_darwin.h
index 32a5f52..3a4cc6f 100644
--- a/redo/objc_darwin.h
+++ b/redo/objc_darwin.h
@@ -59,5 +59,6 @@ extern id newTable(void);
 extern void tableAppendColumn(id, char *);
 extern void tableUpdate(id);
 extern id newScrollView(id);
+extern void tableMakeDataSource(id, void *);
 
 #endif
diff --git a/redo/table_darwin.go b/redo/table_darwin.go
index 91a57ac..206820a 100644
--- a/redo/table_darwin.go
+++ b/redo/table_darwin.go
@@ -3,7 +3,7 @@
 package ui
 
 import (
-//	"fmt"
+	"fmt"
 	"reflect"
 	"unsafe"
 )
@@ -26,7 +26,7 @@ func finishNewTable(b *tablebase, ty reflect.Type) Table {
 		tablebase:		b,
 		table:		id,
 	}
-	// TODO model
+	C.tableMakeDataSource(t.table, unsafe.Pointer(t))
 	for i := 0; i < ty.NumField(); i++ {
 		cname := C.CString(ty.Field(i).Name)
 		C.tableAppendColumn(t.table, cname)
@@ -43,3 +43,23 @@ func (t *table) Unlock() {
 	defer t.RUnlock()
 	C.tableUpdate(t.table)
 }
+
+//export goTableDataSource_getValue
+func goTableDataSource_getValue(data unsafe.Pointer, row C.intptr_t, col C.intptr_t) *C.char {
+	t := (*table)(data)
+	t.RLock()
+	defer t.RUnlock()
+	d := reflect.Indirect(reflect.ValueOf(t.data))
+	datum := d.Index(int(row)).Field(int(col))
+	s := fmt.Sprintf("%v", datum)
+	return C.CString(s)
+}
+
+//export goTableDataSource_getRowCount
+func goTableDataSource_getRowCount(data unsafe.Pointer) C.intptr_t {
+	t := (*table)(data)
+	t.RLock()
+	defer t.RUnlock()
+	d := reflect.Indirect(reflect.ValueOf(t.data))
+	return C.intptr_t(d.Len())
+}
diff --git a/redo/table_darwin.m b/redo/table_darwin.m
index 45e9b0b..7fdef24 100644
--- a/redo/table_darwin.m
+++ b/redo/table_darwin.m
@@ -14,6 +14,24 @@
 @end
 
 @implementation goTableDataSource
+
+- (NSInteger)numberOfRowsInTableView:(NSTableView *)view
+{
+	return (NSInteger) goTableDataSource_getRowCount(self->gotable);
+}
+
+- (id)tableView:(NSTableView *)view objectValueForTableColumn:(NSTableColumn *)col row:(NSInteger)row
+{
+	char *str;
+	NSString *s;
+
+	// TODO there has to be a better way to get the column index
+	str = goTableDataSource_getValue(self->gotable, (intptr_t) row, (intptr_t) [[view tableColumns] indexOfObject:col]);
+	s = [NSString stringWithUTF8String:str];
+	free(str);		// allocated with C.CString() on the Go side
+	return s;
+}
+
 @end
 
 id newTable(void)
@@ -59,3 +77,12 @@ id newScrollView(id content)
 	[sv setDocumentView:toNSView(content)];
 	return (id) sv;
 }
+
+void tableMakeDataSource(id table, void *gotable)
+{
+	goTableDataSource *model;
+
+	model = [goTableDataSource new];
+	model->gotable = gotable;
+	[toNSTableView(table) setDataSource:model];
+}