Skip to content

Instantly share code, notes, and snippets.

@kylehowells
Created May 9, 2019 13:06
Show Gist options
  • Save kylehowells/f81e317866af8c767ed97730fc4b5ecf to your computer and use it in GitHub Desktop.
Save kylehowells/f81e317866af8c767ed97730fc4b5ecf to your computer and use it in GitHub Desktop.
Monitor iOS files for changes using GCD dispatch_source_create DISPATCH_SOURCE_TYPE_VNODE in Xamarin
using System;
using ObjCRuntime;
using Foundation;
using CoreFoundation;
using System.IO;
namespace LoadRuntimeXAML.iOS
{
public class FileWatcher : IDisposable
{
public void Dispose()
{
StopFileMonitoring();
}
public FileWatcher(string filePath) : base(filePath)
{
Path = filePath;
StartMonitoringFile();
}
private void StartMonitoringFile()
{
fileMonitorSource?.Cancel();
fileMonitorSource = null;
var stream = File.OpenRead(Path);
int fileDescriptor = stream.SafeFileHandle.DangerousGetHandle().ToInt32();
fileMonitorSource = new DispatchSource.VnodeMonitor(fileDescriptor, VnodeMonitorKind.Delete | VnodeMonitorKind.Extend | VnodeMonitorKind.Write, DispatchQueue.MainQueue);
fileMonitorSource.SetEventHandler(() =>
{
var observedEvents = fileMonitorSource.ObservedEvents;
Console.WriteLine("Vnode monitor event: {0} for file: {1}", observedEvents, Path);
if (observedEvents.HasFlag(VnodeMonitorKind.Delete))
{
FileDeleted();
}
FileChangedEvent?.Invoke(this, Path);
});
fileMonitorSource.SetCancelHandler(() =>
{
stream.Close();
});
fileMonitorSource.Resume();
}
private void StopFileMonitoring()
{
fileMonitorSource?.Cancel();
fileMonitorSource = null;
}
private void FileDeleted()
{
StopFileMonitoring();
if (File.Exists(Path))
{
StartMonitoringFile();
return;
}
else
{
// Some editors delete and replace the file on save, instead of actually saving and modifying the file.
DispatchQueue.MainQueue.DispatchAfter(new DispatchTime(DispatchTime.Now, TimeSpan.FromSeconds(0.5)), () =>
{
FileDeleted();
});
}
}
private DispatchSource.VnodeMonitor fileMonitorSource;
public string Path { get; }
public event FileChanged FileChangedEvent;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment