Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to make it work with NSTableViewDataSource? #8

Closed
onmyway133 opened this issue Aug 28, 2016 · 12 comments
Closed

How to make it work with NSTableViewDataSource? #8

onmyway133 opened this issue Aug 28, 2016 · 12 comments

Comments

@onmyway133
Copy link

onmyway133 commented Aug 28, 2016

Hi, I'm trying to make it work with NSTableViewDataSource here https://github.com/onmyway133/Sketch-Action/blob/master/SketchAction.sketchplugin/Contents/Sketch/ui.js#L13

var manager = {
  delegate: new MochaJSDelegate(),
  datasource: new MochaJSDelegate(),
  items: ["one", "two", "three"],

  setup: function() {
    this.datasource.setHandlerForSelector("numberOfRowsInTableView:", function(tableView) {
      return this.items.length
    })

    this.datasource.setHandlerForSelector("tableView:objectValueForTableColumn:row:", function(tableView, column, row) {
      return "hello"
    })
  }
}

but the callback is not called. I must be doing something wrong. Thanks

@matt-curtis
Copy link
Owner

matt-curtis commented Aug 28, 2016

@onmyway133 If I had to guess, your problem is in the line:

return this.items.length

this won't refer to your manager object anymore, due to scoping. Also, make sure that your both your dataSource and delegate objects aren't getting released - NSTableView will not retain them.

@onmyway133
Copy link
Author

@matt-curtis thanks for reply

Even if I change to return 10, the callback does not get called. I log / print inside the callback, but there is no long at all

@matt-curtis
Copy link
Owner

matt-curtis commented Aug 28, 2016

Did you check to make sure your delegates were being retained? Try log(tableView.datasource) at various points to make sure it is not nil/undefined. If it still does not work, you may want to research and ensure you are setting up your NSTableView properly.

EDIT:

I just did my own testing and confirmed it - your delegate/datasource is being released. Try assigning them to your manager object, which should keep them around, and from being garbage collected by the Javascript context.

@onmyway133
Copy link
Author

@matt-curtis thanks

I just changed the code to

var manager = {
  delegateClass: new MochaJSDelegate(),
  delegate: null,
  dataSourceClass: new MochaJSDelegate(),
  dataSource: null,
  items: ["one", "two", "three"],

  setup: function() {
    this.dataSourceClass.setHandlerForSelector("numberOfRowsInTableView:", function(tableView) {
      log("hello")
      return 10
    })

    this.dataSourceClass.setHandlerForSelector("tableView:objectValueForTableColumn:row:", function(tableView, column, row) {
      log("world")
      return "hello"
    })

    this.delegate = this.delegateClass.getClassInstance()
    this.dataSource = this.dataSourceClass.getClassInstance()
  }
}

So after setup(), I keep delegate and dataSource inside manager, which is a global var. I log and manager.dataSource and tableView.dataSource are not nil. But the callbacks are not called

@matt-curtis
Copy link
Owner

I don't think this is a problem with MochaJSDelegate. I seems like a problem with how your configuring your NSTableView, but I can't say much beyond that.

@onmyway133
Copy link
Author

onmyway133 commented Aug 29, 2016

@matt-curtis Hi, if I change from

tableView.dataSource = manager.dataSource
tableView.delegate = manager.delegate

to

tableView.setDataSource(manager.dataSource)
tableView.setDelegate(manager.delegate)

Then it crashes. I think it can recognizes the dataSource now, but crash for some reasons

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   com.apple.JavaScriptCore        0x00007fff89ca51f0 JSObjectCallAsFunction + 400
1   com.cocoascript.CocoaScript     0x000000010eb6bae6 __MOGetBlockForJavaScriptFunction_block_invoke + 636
2   com.apple.AppKit                0x00007fff88d2ca0d -[NSTableView preparedCellAtColumn:row:] + 424
3   com.apple.AppKit                0x00007fff88be92c4 -[NSTableView _dirtyVisibleCellsForKeyStateChange] + 782
4   com.apple.AppKit                0x00007fff88be7f04 -[NSTableView _windowChangedKeyState] + 266
5   com.apple.AppKit                0x00007fff88b52d48 -[NSView _windowChangedKeyState] + 299
6   com.apple.AppKit                0x00007fff88b52d48 -[NSView _windowChangedKeyState] + 299
7   com.apple.AppKit                0x00007fff88be7d58 -[NSScrollView _windowChangedKeyState] + 45
8   com.apple.AppKit                0x00007fff88b52d48 -[NSView _windowChangedKeyState] + 299
9   com.apple.AppKit                0x00007fff88b52d48 -[NSView _windowChangedKeyState] + 299
10  com.apple.AppKit                0x00007fff88be732a -[NSThemeFrame _windowChangedKeyState] + 47

If I disable dataSource, and keep the delegate

//tableView.setDataSource(manager.dataSource)
tableView.setDelegate(manager.delegate)

then it works

this.delegateClass.setHandlerForSelector("tableView:didClickTableColumn:", function(tableView, column) {
      log("did click column")
})

Is that because MochaJSDelegate can't handle function with return value?

@onmyway133
Copy link
Author

I think we can create a Cocoa framework and load it from Sketch, but this is more challenging

@onmyway133
Copy link
Author

onmyway133 commented Aug 29, 2016

With dataSource set

this.dataSourceClass.setHandlerForSelector("numberOfRowsInTableView:", function(tableView) {
      log("numberOfRowsInTableView")
      return 2
    })

    this.dataSourceClass.setHandlerForSelector("tableView:objectValueForTableColumn:row:", function(tableView, column, row) {
      log("objectValueForTableColumn")
      return "hello"
    })

I get the logs before it crashes. So the dataSource works 🎉

numberOfRowsInTableView // 3 times
objectValueForTableColumn // 1 time

I think it has to do with NSTableView cell based configuration

@matt-curtis
Copy link
Owner

matt-curtis commented Aug 29, 2016

This looks like a bug with how Mocha hands over return values to Objective-C to me (somewhere around here), to be honest. I think I've I've seen this bug before, but I can't recall where exactly. Your best bet is probably to try the framework route. I think Mocha may also not like the fact that the method expects id as a return type.

@onmyway133
Copy link
Author

@matt-curtis thanks for your help

@onmyway133
Copy link
Author

onmyway133 commented Sep 5, 2016

@matt-curtis Hi, so I went with the Cocoa framework approach. It is much much easier to test, debug within a Cocoa app, you can check it out https://github.com/onmyway133/Sketch-Action

Have no idea why Sketch chose to use CocoaScript for plugin development, hope that it is not about the syntax, it does not worth it 😓

@matt-curtis
Copy link
Owner

Nice work! Starred. 🌟

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants