Created
May 9, 2019 13:06
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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