tombenner / nui

Style iOS apps with a stylesheet, similar to CSS
MIT License
3.76k stars 461 forks source link

autoUpdate NUI using setAutoUpdatePath #207

Open rahulsingh2k10 opened 10 years ago

rahulsingh2k10 commented 10 years ago

How can I update my NUI using [NUISettings setAutoUpdatePath:@"/path/to/Style.nss"]; becoz when I place this method on the button press noting is happening. Basically, I want that when a user presses a button the theme should be changed.How can I achieve this?

phatmann commented 10 years ago

The way to do it is to call [NUISettings initWithStylesheet:name] and then [NUIRenderer rerender], but unfortunately rerender is not public. It think it would be best if NUISettings provided a single method to do this. Maybe you could make the appropriate change and file a pull request?

phatmann commented 10 years ago

On second thought, both NUISettings.initWithStylesheet and NUISettings.appendStylesheet:name should call NUIRenderer.rerender so they work from anywhere. Try adding this call to both methods and see if your theme reloading works. If it does, let us know and/or submit a pull request.

phatmann commented 10 years ago

On third thought...it is not good to call an init method more than once. We should add a setStylesheetmethod to NUISettings. That is what you would use to change themes, and it would call rererender.

No fourth thought, I promise :-)

leberwurstsaft commented 10 years ago

Auto update isn't working the way I understood it should work. I tried both the direct path to the project folder and the path in the .app container like below.

Manipulating the .nss and saving it doesn't trigger rerendering.

What am I missing?

[NUISettings initWithStylesheet:@"style"];
NSString *path = [[NSBundle mainBundle] pathForResource:@"style" ofType:@"nss"];
[NUISettings setAutoUpdatePath:path];
leberwurstsaft commented 10 years ago

Ok, as far as I can tell, auto updating can't work like this.

In +getInstance of NUIRenderer is a check for autoUpdateIsEnabled on NUISettings. However, the renderer will be created only once and it's before NUISettings gets told about the path to the .nss to watch over. So, the simple solution is to -initWithStyleSheet: only after -setAutoUpdatePath:.

Checking again in the Readme, it suggests to add -setAutoUpdatePath: after [NUISettings init];, (not -initWithStyleSheet), but that only loads the default style sheet.

runeb commented 10 years ago

auto update is working very poorly here. How about watching changes in the nss file with GDC? Example code:

  const char *fileSysRef = "/path/to/theme.nss";
  _fileDescriptor = open(fileSysRef, O_RDONLY);
  _queue = dispatch_queue_create("NUI File Change Monitor Queue", 0);
  // watch the file descriptor for writes
  unsigned long mask = DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_LINK | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE;
  _source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, _fileDescriptor, mask, _queue);

  // call the passed block if the source is modified
  _block = ^{
    unsigned long l = dispatch_source_get_data(_source);
    if(l & 0x32) {
      // File has changes, trigger reload
      NSLog(@"File has changes, should reload styleheet");
    }
    if (l & DISPATCH_VNODE_DELETE) {
      NSLog(@"watched file deleted!  cancelling source");
      dispatch_source_cancel(_source);
    }
  };

  dispatch_source_set_event_handler(_source, _block);

  // close the file descriptor when the dispatch source is cancelled
  dispatch_source_set_cancel_handler(_source, ^{
    int fdes = dispatch_source_get_handle(_source);
    close(fdes);
    // Wait for new file to exist.
    while ((fdes = open(fileSysRef, O_RDONLY)) == -1)
      sleep(1);
    NSLog(@"re-opened target file in cancel handler");
    _source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fdes, mask, _queue);
    dispatch_source_set_event_handler(_source, _block);
    dispatch_source_set_cancel_handler(_source, _block);
    dispatch_resume(_source);
  });

  // at this point the dispatch source is paused, so start watching
  dispatch_resume(_source);