├── .gitignore ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── contents.xcworkspacedata ├── .travis.yml ├── BuildTest ├── BuildTest.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── MacCatalystBuildTest │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Info.plist │ ├── MacCatalystBuildTest.entitlements │ └── Preview Content │ │ └── Preview Assets.xcassets │ │ └── Contents.json └── MacOSBuildTest │ └── main.swift ├── EonilFSEventsDemoGUI ├── EonilFSEventsDemoGUI.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── EonilFSEventsDemoGUI.xcscheme └── EonilFSEventsDemoGUI │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ └── Main.storyboard │ ├── EonilFSEventsDemoGUI.entitlements │ ├── Info.plist │ └── ViewController.swift ├── LICENSE.md ├── Package.swift ├── README.md ├── Sources ├── EonilFSEvents │ ├── EonilFSEventStream.swift │ ├── EonilFSEventStreamCreateFlags.swift │ ├── EonilFSEventStreamError.swift │ ├── EonilFSEventStreamEvent.swift │ ├── EonilFSEventStreamEventFlags.swift │ ├── EonilFSEventStreamEventID.swift │ ├── EonilFSEventStreamIllogicalErrorLog.swift │ └── EonilFSEvents.swift └── EonilFSEventsDemoCLI │ └── main.swift └── test.zsh /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /build 3 | .build 4 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: swift 2 | os: osx 3 | osx_image: xcode11 4 | script: zsh test.zsh 5 | -------------------------------------------------------------------------------- /BuildTest/BuildTest.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 52; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D74D88E72498C12A00A0F885 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74D88E62498C12A00A0F885 /* main.swift */; }; 11 | D74D88F22498C16200A0F885 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74D88F12498C16200A0F885 /* AppDelegate.swift */; }; 12 | D74D88F82498C16500A0F885 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D74D88F72498C16500A0F885 /* Assets.xcassets */; }; 13 | D74D88FB2498C16500A0F885 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D74D88FA2498C16500A0F885 /* Preview Assets.xcassets */; }; 14 | D74D88FE2498C16500A0F885 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D74D88FC2498C16500A0F885 /* LaunchScreen.storyboard */; }; 15 | D74D89072498C1A600A0F885 /* EonilFSEvents in Frameworks */ = {isa = PBXBuildFile; platformFilter = maccatalyst; productRef = D74D89062498C1A600A0F885 /* EonilFSEvents */; }; 16 | D74D89092498C1AC00A0F885 /* EonilFSEvents in Frameworks */ = {isa = PBXBuildFile; productRef = D74D89082498C1AC00A0F885 /* EonilFSEvents */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXCopyFilesBuildPhase section */ 20 | D74D88E12498C12A00A0F885 /* CopyFiles */ = { 21 | isa = PBXCopyFilesBuildPhase; 22 | buildActionMask = 2147483647; 23 | dstPath = /usr/share/man/man1/; 24 | dstSubfolderSpec = 0; 25 | files = ( 26 | ); 27 | runOnlyForDeploymentPostprocessing = 1; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | D74D88E32498C12A00A0F885 /* MacOSBuildTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MacOSBuildTest; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | D74D88E62498C12A00A0F885 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 34 | D74D88EF2498C16200A0F885 /* MacCatalystBuildTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MacCatalystBuildTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | D74D88F12498C16200A0F885 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 36 | D74D88F72498C16500A0F885 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 37 | D74D88FA2498C16500A0F885 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 38 | D74D88FD2498C16500A0F885 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 39 | D74D88FF2498C16500A0F885 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | D74D89032498C16B00A0F885 /* MacCatalystBuildTest.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MacCatalystBuildTest.entitlements; sourceTree = ""; }; 41 | D74D89042498C1A200A0F885 /* FSEvents */ = {isa = PBXFileReference; lastKnownFileType = folder; name = FSEvents; path = ..; sourceTree = ""; }; 42 | /* End PBXFileReference section */ 43 | 44 | /* Begin PBXFrameworksBuildPhase section */ 45 | D74D88E02498C12A00A0F885 /* Frameworks */ = { 46 | isa = PBXFrameworksBuildPhase; 47 | buildActionMask = 2147483647; 48 | files = ( 49 | D74D89092498C1AC00A0F885 /* EonilFSEvents in Frameworks */, 50 | ); 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | D74D88EC2498C16200A0F885 /* Frameworks */ = { 54 | isa = PBXFrameworksBuildPhase; 55 | buildActionMask = 2147483647; 56 | files = ( 57 | D74D89072498C1A600A0F885 /* EonilFSEvents in Frameworks */, 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | D74D88D82498C10A00A0F885 = { 65 | isa = PBXGroup; 66 | children = ( 67 | D74D89042498C1A200A0F885 /* FSEvents */, 68 | D74D88E52498C12A00A0F885 /* MacOSBuildTest */, 69 | D74D88F02498C16200A0F885 /* MacCatalystBuildTest */, 70 | D74D88E42498C12A00A0F885 /* Products */, 71 | D74D89052498C1A600A0F885 /* Frameworks */, 72 | ); 73 | sourceTree = ""; 74 | }; 75 | D74D88E42498C12A00A0F885 /* Products */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | D74D88E32498C12A00A0F885 /* MacOSBuildTest */, 79 | D74D88EF2498C16200A0F885 /* MacCatalystBuildTest.app */, 80 | ); 81 | name = Products; 82 | sourceTree = ""; 83 | }; 84 | D74D88E52498C12A00A0F885 /* MacOSBuildTest */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | D74D88E62498C12A00A0F885 /* main.swift */, 88 | ); 89 | path = MacOSBuildTest; 90 | sourceTree = ""; 91 | }; 92 | D74D88F02498C16200A0F885 /* MacCatalystBuildTest */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | D74D89032498C16B00A0F885 /* MacCatalystBuildTest.entitlements */, 96 | D74D88F12498C16200A0F885 /* AppDelegate.swift */, 97 | D74D88F72498C16500A0F885 /* Assets.xcassets */, 98 | D74D88FC2498C16500A0F885 /* LaunchScreen.storyboard */, 99 | D74D88FF2498C16500A0F885 /* Info.plist */, 100 | D74D88F92498C16500A0F885 /* Preview Content */, 101 | ); 102 | path = MacCatalystBuildTest; 103 | sourceTree = ""; 104 | }; 105 | D74D88F92498C16500A0F885 /* Preview Content */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | D74D88FA2498C16500A0F885 /* Preview Assets.xcassets */, 109 | ); 110 | path = "Preview Content"; 111 | sourceTree = ""; 112 | }; 113 | D74D89052498C1A600A0F885 /* Frameworks */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | ); 117 | name = Frameworks; 118 | sourceTree = ""; 119 | }; 120 | /* End PBXGroup section */ 121 | 122 | /* Begin PBXNativeTarget section */ 123 | D74D88E22498C12A00A0F885 /* MacOSBuildTest */ = { 124 | isa = PBXNativeTarget; 125 | buildConfigurationList = D74D88E82498C12A00A0F885 /* Build configuration list for PBXNativeTarget "MacOSBuildTest" */; 126 | buildPhases = ( 127 | D74D88DF2498C12A00A0F885 /* Sources */, 128 | D74D88E02498C12A00A0F885 /* Frameworks */, 129 | D74D88E12498C12A00A0F885 /* CopyFiles */, 130 | ); 131 | buildRules = ( 132 | ); 133 | dependencies = ( 134 | ); 135 | name = MacOSBuildTest; 136 | packageProductDependencies = ( 137 | D74D89082498C1AC00A0F885 /* EonilFSEvents */, 138 | ); 139 | productName = MacOSBuildTest; 140 | productReference = D74D88E32498C12A00A0F885 /* MacOSBuildTest */; 141 | productType = "com.apple.product-type.tool"; 142 | }; 143 | D74D88EE2498C16200A0F885 /* MacCatalystBuildTest */ = { 144 | isa = PBXNativeTarget; 145 | buildConfigurationList = D74D89002498C16500A0F885 /* Build configuration list for PBXNativeTarget "MacCatalystBuildTest" */; 146 | buildPhases = ( 147 | D74D88EB2498C16200A0F885 /* Sources */, 148 | D74D88EC2498C16200A0F885 /* Frameworks */, 149 | D74D88ED2498C16200A0F885 /* Resources */, 150 | ); 151 | buildRules = ( 152 | ); 153 | dependencies = ( 154 | ); 155 | name = MacCatalystBuildTest; 156 | packageProductDependencies = ( 157 | D74D89062498C1A600A0F885 /* EonilFSEvents */, 158 | ); 159 | productName = MacCatalystBuildTest; 160 | productReference = D74D88EF2498C16200A0F885 /* MacCatalystBuildTest.app */; 161 | productType = "com.apple.product-type.application"; 162 | }; 163 | /* End PBXNativeTarget section */ 164 | 165 | /* Begin PBXProject section */ 166 | D74D88D92498C10A00A0F885 /* Project object */ = { 167 | isa = PBXProject; 168 | attributes = { 169 | LastSwiftUpdateCheck = 1150; 170 | LastUpgradeCheck = 1150; 171 | TargetAttributes = { 172 | D74D88E22498C12A00A0F885 = { 173 | CreatedOnToolsVersion = 11.5; 174 | }; 175 | D74D88EE2498C16200A0F885 = { 176 | CreatedOnToolsVersion = 11.5; 177 | }; 178 | }; 179 | }; 180 | buildConfigurationList = D74D88DC2498C10A00A0F885 /* Build configuration list for PBXProject "BuildTest" */; 181 | compatibilityVersion = "Xcode 9.3"; 182 | developmentRegion = en; 183 | hasScannedForEncodings = 0; 184 | knownRegions = ( 185 | en, 186 | Base, 187 | ); 188 | mainGroup = D74D88D82498C10A00A0F885; 189 | productRefGroup = D74D88E42498C12A00A0F885 /* Products */; 190 | projectDirPath = ""; 191 | projectRoot = ""; 192 | targets = ( 193 | D74D88E22498C12A00A0F885 /* MacOSBuildTest */, 194 | D74D88EE2498C16200A0F885 /* MacCatalystBuildTest */, 195 | ); 196 | }; 197 | /* End PBXProject section */ 198 | 199 | /* Begin PBXResourcesBuildPhase section */ 200 | D74D88ED2498C16200A0F885 /* Resources */ = { 201 | isa = PBXResourcesBuildPhase; 202 | buildActionMask = 2147483647; 203 | files = ( 204 | D74D88FE2498C16500A0F885 /* LaunchScreen.storyboard in Resources */, 205 | D74D88FB2498C16500A0F885 /* Preview Assets.xcassets in Resources */, 206 | D74D88F82498C16500A0F885 /* Assets.xcassets in Resources */, 207 | ); 208 | runOnlyForDeploymentPostprocessing = 0; 209 | }; 210 | /* End PBXResourcesBuildPhase section */ 211 | 212 | /* Begin PBXSourcesBuildPhase section */ 213 | D74D88DF2498C12A00A0F885 /* Sources */ = { 214 | isa = PBXSourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | D74D88E72498C12A00A0F885 /* main.swift in Sources */, 218 | ); 219 | runOnlyForDeploymentPostprocessing = 0; 220 | }; 221 | D74D88EB2498C16200A0F885 /* Sources */ = { 222 | isa = PBXSourcesBuildPhase; 223 | buildActionMask = 2147483647; 224 | files = ( 225 | D74D88F22498C16200A0F885 /* AppDelegate.swift in Sources */, 226 | ); 227 | runOnlyForDeploymentPostprocessing = 0; 228 | }; 229 | /* End PBXSourcesBuildPhase section */ 230 | 231 | /* Begin PBXVariantGroup section */ 232 | D74D88FC2498C16500A0F885 /* LaunchScreen.storyboard */ = { 233 | isa = PBXVariantGroup; 234 | children = ( 235 | D74D88FD2498C16500A0F885 /* Base */, 236 | ); 237 | name = LaunchScreen.storyboard; 238 | sourceTree = ""; 239 | }; 240 | /* End PBXVariantGroup section */ 241 | 242 | /* Begin XCBuildConfiguration section */ 243 | D74D88DD2498C10A00A0F885 /* Debug */ = { 244 | isa = XCBuildConfiguration; 245 | buildSettings = { 246 | }; 247 | name = Debug; 248 | }; 249 | D74D88DE2498C10A00A0F885 /* Release */ = { 250 | isa = XCBuildConfiguration; 251 | buildSettings = { 252 | }; 253 | name = Release; 254 | }; 255 | D74D88E92498C12A00A0F885 /* Debug */ = { 256 | isa = XCBuildConfiguration; 257 | buildSettings = { 258 | ALWAYS_SEARCH_USER_PATHS = NO; 259 | CLANG_ANALYZER_NONNULL = YES; 260 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 261 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 262 | CLANG_CXX_LIBRARY = "libc++"; 263 | CLANG_ENABLE_MODULES = YES; 264 | CLANG_ENABLE_OBJC_ARC = YES; 265 | CLANG_ENABLE_OBJC_WEAK = YES; 266 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 267 | CLANG_WARN_BOOL_CONVERSION = YES; 268 | CLANG_WARN_COMMA = YES; 269 | CLANG_WARN_CONSTANT_CONVERSION = YES; 270 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 271 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 272 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 273 | CLANG_WARN_EMPTY_BODY = YES; 274 | CLANG_WARN_ENUM_CONVERSION = YES; 275 | CLANG_WARN_INFINITE_RECURSION = YES; 276 | CLANG_WARN_INT_CONVERSION = YES; 277 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 278 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 279 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 280 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 281 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 282 | CLANG_WARN_STRICT_PROTOTYPES = YES; 283 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 284 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 285 | CLANG_WARN_UNREACHABLE_CODE = YES; 286 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 287 | CODE_SIGN_STYLE = Automatic; 288 | COPY_PHASE_STRIP = NO; 289 | DEBUG_INFORMATION_FORMAT = dwarf; 290 | ENABLE_STRICT_OBJC_MSGSEND = YES; 291 | ENABLE_TESTABILITY = YES; 292 | GCC_C_LANGUAGE_STANDARD = gnu11; 293 | GCC_DYNAMIC_NO_PIC = NO; 294 | GCC_NO_COMMON_BLOCKS = YES; 295 | GCC_OPTIMIZATION_LEVEL = 0; 296 | GCC_PREPROCESSOR_DEFINITIONS = ( 297 | "DEBUG=1", 298 | "$(inherited)", 299 | ); 300 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 301 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 302 | GCC_WARN_UNDECLARED_SELECTOR = YES; 303 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 304 | GCC_WARN_UNUSED_FUNCTION = YES; 305 | GCC_WARN_UNUSED_VARIABLE = YES; 306 | MACOSX_DEPLOYMENT_TARGET = 10.15; 307 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 308 | MTL_FAST_MATH = YES; 309 | ONLY_ACTIVE_ARCH = YES; 310 | PRODUCT_NAME = "$(TARGET_NAME)"; 311 | SDKROOT = macosx; 312 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 313 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 314 | SWIFT_VERSION = 5.0; 315 | }; 316 | name = Debug; 317 | }; 318 | D74D88EA2498C12A00A0F885 /* Release */ = { 319 | isa = XCBuildConfiguration; 320 | buildSettings = { 321 | ALWAYS_SEARCH_USER_PATHS = NO; 322 | CLANG_ANALYZER_NONNULL = YES; 323 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 324 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 325 | CLANG_CXX_LIBRARY = "libc++"; 326 | CLANG_ENABLE_MODULES = YES; 327 | CLANG_ENABLE_OBJC_ARC = YES; 328 | CLANG_ENABLE_OBJC_WEAK = YES; 329 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 330 | CLANG_WARN_BOOL_CONVERSION = YES; 331 | CLANG_WARN_COMMA = YES; 332 | CLANG_WARN_CONSTANT_CONVERSION = YES; 333 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 334 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 335 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 336 | CLANG_WARN_EMPTY_BODY = YES; 337 | CLANG_WARN_ENUM_CONVERSION = YES; 338 | CLANG_WARN_INFINITE_RECURSION = YES; 339 | CLANG_WARN_INT_CONVERSION = YES; 340 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 341 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 342 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 343 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 344 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 345 | CLANG_WARN_STRICT_PROTOTYPES = YES; 346 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 347 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 348 | CLANG_WARN_UNREACHABLE_CODE = YES; 349 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 350 | CODE_SIGN_STYLE = Automatic; 351 | COPY_PHASE_STRIP = NO; 352 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 353 | ENABLE_NS_ASSERTIONS = NO; 354 | ENABLE_STRICT_OBJC_MSGSEND = YES; 355 | GCC_C_LANGUAGE_STANDARD = gnu11; 356 | GCC_NO_COMMON_BLOCKS = YES; 357 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 358 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 359 | GCC_WARN_UNDECLARED_SELECTOR = YES; 360 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 361 | GCC_WARN_UNUSED_FUNCTION = YES; 362 | GCC_WARN_UNUSED_VARIABLE = YES; 363 | MACOSX_DEPLOYMENT_TARGET = 10.15; 364 | MTL_ENABLE_DEBUG_INFO = NO; 365 | MTL_FAST_MATH = YES; 366 | PRODUCT_NAME = "$(TARGET_NAME)"; 367 | SDKROOT = macosx; 368 | SWIFT_COMPILATION_MODE = wholemodule; 369 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 370 | SWIFT_VERSION = 5.0; 371 | }; 372 | name = Release; 373 | }; 374 | D74D89012498C16500A0F885 /* Debug */ = { 375 | isa = XCBuildConfiguration; 376 | buildSettings = { 377 | ALWAYS_SEARCH_USER_PATHS = NO; 378 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 379 | CLANG_ANALYZER_NONNULL = YES; 380 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 381 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 382 | CLANG_CXX_LIBRARY = "libc++"; 383 | CLANG_ENABLE_MODULES = YES; 384 | CLANG_ENABLE_OBJC_ARC = YES; 385 | CLANG_ENABLE_OBJC_WEAK = YES; 386 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 387 | CLANG_WARN_BOOL_CONVERSION = YES; 388 | CLANG_WARN_COMMA = YES; 389 | CLANG_WARN_CONSTANT_CONVERSION = YES; 390 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 391 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 392 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 393 | CLANG_WARN_EMPTY_BODY = YES; 394 | CLANG_WARN_ENUM_CONVERSION = YES; 395 | CLANG_WARN_INFINITE_RECURSION = YES; 396 | CLANG_WARN_INT_CONVERSION = YES; 397 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 398 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 399 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 400 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 401 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 402 | CLANG_WARN_STRICT_PROTOTYPES = YES; 403 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 404 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 405 | CLANG_WARN_UNREACHABLE_CODE = YES; 406 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 407 | CODE_SIGN_ENTITLEMENTS = MacCatalystBuildTest/MacCatalystBuildTest.entitlements; 408 | CODE_SIGN_IDENTITY = "Apple Development"; 409 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; 410 | CODE_SIGN_STYLE = Manual; 411 | COPY_PHASE_STRIP = NO; 412 | DEBUG_INFORMATION_FORMAT = dwarf; 413 | DEVELOPMENT_ASSET_PATHS = "\"MacCatalystBuildTest/Preview Content\""; 414 | DEVELOPMENT_TEAM = ""; 415 | ENABLE_PREVIEWS = YES; 416 | ENABLE_STRICT_OBJC_MSGSEND = YES; 417 | ENABLE_TESTABILITY = YES; 418 | GCC_C_LANGUAGE_STANDARD = gnu11; 419 | GCC_DYNAMIC_NO_PIC = NO; 420 | GCC_NO_COMMON_BLOCKS = YES; 421 | GCC_OPTIMIZATION_LEVEL = 0; 422 | GCC_PREPROCESSOR_DEFINITIONS = ( 423 | "DEBUG=1", 424 | "$(inherited)", 425 | ); 426 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 427 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 428 | GCC_WARN_UNDECLARED_SELECTOR = YES; 429 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 430 | GCC_WARN_UNUSED_FUNCTION = YES; 431 | GCC_WARN_UNUSED_VARIABLE = YES; 432 | INFOPLIST_FILE = MacCatalystBuildTest/Info.plist; 433 | IPHONEOS_DEPLOYMENT_TARGET = 13.4; 434 | LD_RUNPATH_SEARCH_PATHS = ( 435 | "$(inherited)", 436 | "@executable_path/Frameworks", 437 | ); 438 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 439 | MTL_FAST_MATH = YES; 440 | ONLY_ACTIVE_ARCH = YES; 441 | PRODUCT_BUNDLE_IDENTIFIER = Eonil.MacCatalystBuildTest; 442 | PRODUCT_NAME = "$(TARGET_NAME)"; 443 | PROVISIONING_PROFILE_SPECIFIER = ""; 444 | "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; 445 | SDKROOT = iphoneos; 446 | SUPPORTS_MACCATALYST = YES; 447 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 448 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 449 | SWIFT_VERSION = 5.0; 450 | TARGETED_DEVICE_FAMILY = 2; 451 | }; 452 | name = Debug; 453 | }; 454 | D74D89022498C16500A0F885 /* Release */ = { 455 | isa = XCBuildConfiguration; 456 | buildSettings = { 457 | ALWAYS_SEARCH_USER_PATHS = NO; 458 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 459 | CLANG_ANALYZER_NONNULL = YES; 460 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 461 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 462 | CLANG_CXX_LIBRARY = "libc++"; 463 | CLANG_ENABLE_MODULES = YES; 464 | CLANG_ENABLE_OBJC_ARC = YES; 465 | CLANG_ENABLE_OBJC_WEAK = YES; 466 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 467 | CLANG_WARN_BOOL_CONVERSION = YES; 468 | CLANG_WARN_COMMA = YES; 469 | CLANG_WARN_CONSTANT_CONVERSION = YES; 470 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 471 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 472 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 473 | CLANG_WARN_EMPTY_BODY = YES; 474 | CLANG_WARN_ENUM_CONVERSION = YES; 475 | CLANG_WARN_INFINITE_RECURSION = YES; 476 | CLANG_WARN_INT_CONVERSION = YES; 477 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 478 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 479 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 480 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 481 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 482 | CLANG_WARN_STRICT_PROTOTYPES = YES; 483 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 484 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 485 | CLANG_WARN_UNREACHABLE_CODE = YES; 486 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 487 | CODE_SIGN_ENTITLEMENTS = MacCatalystBuildTest/MacCatalystBuildTest.entitlements; 488 | CODE_SIGN_IDENTITY = "Apple Development"; 489 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; 490 | CODE_SIGN_STYLE = Manual; 491 | COPY_PHASE_STRIP = NO; 492 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 493 | DEVELOPMENT_ASSET_PATHS = "\"MacCatalystBuildTest/Preview Content\""; 494 | DEVELOPMENT_TEAM = ""; 495 | ENABLE_NS_ASSERTIONS = NO; 496 | ENABLE_PREVIEWS = YES; 497 | ENABLE_STRICT_OBJC_MSGSEND = YES; 498 | GCC_C_LANGUAGE_STANDARD = gnu11; 499 | GCC_NO_COMMON_BLOCKS = YES; 500 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 501 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 502 | GCC_WARN_UNDECLARED_SELECTOR = YES; 503 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 504 | GCC_WARN_UNUSED_FUNCTION = YES; 505 | GCC_WARN_UNUSED_VARIABLE = YES; 506 | INFOPLIST_FILE = MacCatalystBuildTest/Info.plist; 507 | IPHONEOS_DEPLOYMENT_TARGET = 13.4; 508 | LD_RUNPATH_SEARCH_PATHS = ( 509 | "$(inherited)", 510 | "@executable_path/Frameworks", 511 | ); 512 | MTL_ENABLE_DEBUG_INFO = NO; 513 | MTL_FAST_MATH = YES; 514 | PRODUCT_BUNDLE_IDENTIFIER = Eonil.MacCatalystBuildTest; 515 | PRODUCT_NAME = "$(TARGET_NAME)"; 516 | PROVISIONING_PROFILE_SPECIFIER = ""; 517 | "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; 518 | SDKROOT = iphoneos; 519 | SUPPORTS_MACCATALYST = YES; 520 | SWIFT_COMPILATION_MODE = wholemodule; 521 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 522 | SWIFT_VERSION = 5.0; 523 | TARGETED_DEVICE_FAMILY = 2; 524 | VALIDATE_PRODUCT = YES; 525 | }; 526 | name = Release; 527 | }; 528 | /* End XCBuildConfiguration section */ 529 | 530 | /* Begin XCConfigurationList section */ 531 | D74D88DC2498C10A00A0F885 /* Build configuration list for PBXProject "BuildTest" */ = { 532 | isa = XCConfigurationList; 533 | buildConfigurations = ( 534 | D74D88DD2498C10A00A0F885 /* Debug */, 535 | D74D88DE2498C10A00A0F885 /* Release */, 536 | ); 537 | defaultConfigurationIsVisible = 0; 538 | defaultConfigurationName = Release; 539 | }; 540 | D74D88E82498C12A00A0F885 /* Build configuration list for PBXNativeTarget "MacOSBuildTest" */ = { 541 | isa = XCConfigurationList; 542 | buildConfigurations = ( 543 | D74D88E92498C12A00A0F885 /* Debug */, 544 | D74D88EA2498C12A00A0F885 /* Release */, 545 | ); 546 | defaultConfigurationIsVisible = 0; 547 | defaultConfigurationName = Release; 548 | }; 549 | D74D89002498C16500A0F885 /* Build configuration list for PBXNativeTarget "MacCatalystBuildTest" */ = { 550 | isa = XCConfigurationList; 551 | buildConfigurations = ( 552 | D74D89012498C16500A0F885 /* Debug */, 553 | D74D89022498C16500A0F885 /* Release */, 554 | ); 555 | defaultConfigurationIsVisible = 0; 556 | defaultConfigurationName = Release; 557 | }; 558 | /* End XCConfigurationList section */ 559 | 560 | /* Begin XCSwiftPackageProductDependency section */ 561 | D74D89062498C1A600A0F885 /* EonilFSEvents */ = { 562 | isa = XCSwiftPackageProductDependency; 563 | productName = EonilFSEvents; 564 | }; 565 | D74D89082498C1AC00A0F885 /* EonilFSEvents */ = { 566 | isa = XCSwiftPackageProductDependency; 567 | productName = EonilFSEvents; 568 | }; 569 | /* End XCSwiftPackageProductDependency section */ 570 | }; 571 | rootObject = D74D88D92498C10A00A0F885 /* Project object */; 572 | } 573 | -------------------------------------------------------------------------------- /BuildTest/BuildTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BuildTest/BuildTest.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /BuildTest/MacCatalystBuildTest/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // MacCatalystBuildTest 4 | // 5 | // Created by Henry Hathaway on 6/16/20. 6 | // 7 | 8 | import UIKit 9 | 10 | @UIApplicationMain 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 13 | true 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /BuildTest/MacCatalystBuildTest/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /BuildTest/MacCatalystBuildTest/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /BuildTest/MacCatalystBuildTest/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /BuildTest/MacCatalystBuildTest/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /BuildTest/MacCatalystBuildTest/MacCatalystBuildTest.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.network.client 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /BuildTest/MacCatalystBuildTest/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /BuildTest/MacOSBuildTest/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // MacOSBuildTest 4 | // 5 | // Created by Henry Hathaway on 6/16/20. 6 | // 7 | 8 | import Foundation 9 | 10 | print("Hello, World!") 11 | 12 | -------------------------------------------------------------------------------- /EonilFSEventsDemoGUI/EonilFSEventsDemoGUI.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 52; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4513D3E521D533BE0070A7A5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4513D3E421D533BE0070A7A5 /* AppDelegate.swift */; }; 11 | 4513D3E721D533BE0070A7A5 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4513D3E621D533BE0070A7A5 /* ViewController.swift */; }; 12 | 4513D3E921D533C00070A7A5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4513D3E821D533C00070A7A5 /* Assets.xcassets */; }; 13 | 4513D3EC21D533C00070A7A5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4513D3EA21D533C00070A7A5 /* Main.storyboard */; }; 14 | BA53C7BB232B904E00838304 /* EonilFSEvents in Frameworks */ = {isa = PBXBuildFile; productRef = BA53C7BA232B904E00838304 /* EonilFSEvents */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXFileReference section */ 18 | 4513D3E221D533BE0070A7A5 /* EonilFSEventsDemoGUI.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EonilFSEventsDemoGUI.app; sourceTree = BUILT_PRODUCTS_DIR; }; 19 | 4513D3E421D533BE0070A7A5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 20 | 4513D3E621D533BE0070A7A5 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 21 | 4513D3E821D533C00070A7A5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 22 | 4513D3EB21D533C00070A7A5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 23 | 4513D3ED21D533C00070A7A5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 24 | 4513D3EE21D533C00070A7A5 /* EonilFSEventsDemoGUI.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = EonilFSEventsDemoGUI.entitlements; sourceTree = ""; }; 25 | 4513D42421D55AB30070A7A5 /* libFSEventUnofficialWrapperStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libFSEventUnofficialWrapperStream.a; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | 4513D42621D55AB70070A7A5 /* libFSEventUnofficialWrapperStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libFSEventUnofficialWrapperStream.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | D7675AB023457A86002AC0F7 /* FSEvents */ = {isa = PBXFileReference; lastKnownFileType = folder; name = FSEvents; path = ..; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 4513D3DF21D533BE0070A7A5 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | BA53C7BB232B904E00838304 /* EonilFSEvents in Frameworks */, 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | 4513D3CB21D5334D0070A7A5 = { 43 | isa = PBXGroup; 44 | children = ( 45 | D7675AB023457A86002AC0F7 /* FSEvents */, 46 | 4513D3E321D533BE0070A7A5 /* EonilFSEventsDemoGUI */, 47 | 4513D3D721D533B20070A7A5 /* Products */, 48 | 4513D41F21D533EB0070A7A5 /* Frameworks */, 49 | ); 50 | sourceTree = ""; 51 | }; 52 | 4513D3D721D533B20070A7A5 /* Products */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 4513D3E221D533BE0070A7A5 /* EonilFSEventsDemoGUI.app */, 56 | ); 57 | name = Products; 58 | sourceTree = ""; 59 | }; 60 | 4513D3E321D533BE0070A7A5 /* EonilFSEventsDemoGUI */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 4513D3E421D533BE0070A7A5 /* AppDelegate.swift */, 64 | 4513D3E621D533BE0070A7A5 /* ViewController.swift */, 65 | 4513D3E821D533C00070A7A5 /* Assets.xcassets */, 66 | 4513D3EA21D533C00070A7A5 /* Main.storyboard */, 67 | 4513D3ED21D533C00070A7A5 /* Info.plist */, 68 | 4513D3EE21D533C00070A7A5 /* EonilFSEventsDemoGUI.entitlements */, 69 | ); 70 | path = EonilFSEventsDemoGUI; 71 | sourceTree = ""; 72 | }; 73 | 4513D41F21D533EB0070A7A5 /* Frameworks */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 4513D42621D55AB70070A7A5 /* libFSEventUnofficialWrapperStream.a */, 77 | 4513D42421D55AB30070A7A5 /* libFSEventUnofficialWrapperStream.a */, 78 | ); 79 | name = Frameworks; 80 | sourceTree = ""; 81 | }; 82 | /* End PBXGroup section */ 83 | 84 | /* Begin PBXNativeTarget section */ 85 | 4513D3E121D533BE0070A7A5 /* EonilFSEventsDemoGUI */ = { 86 | isa = PBXNativeTarget; 87 | buildConfigurationList = 4513D40521D533C00070A7A5 /* Build configuration list for PBXNativeTarget "EonilFSEventsDemoGUI" */; 88 | buildPhases = ( 89 | 4513D3DE21D533BE0070A7A5 /* Sources */, 90 | 4513D3DF21D533BE0070A7A5 /* Frameworks */, 91 | 4513D3E021D533BE0070A7A5 /* Resources */, 92 | ); 93 | buildRules = ( 94 | ); 95 | dependencies = ( 96 | ); 97 | name = EonilFSEventsDemoGUI; 98 | packageProductDependencies = ( 99 | BA53C7BA232B904E00838304 /* EonilFSEvents */, 100 | ); 101 | productName = FileSystemWatcherDemoGUI; 102 | productReference = 4513D3E221D533BE0070A7A5 /* EonilFSEventsDemoGUI.app */; 103 | productType = "com.apple.product-type.application"; 104 | }; 105 | /* End PBXNativeTarget section */ 106 | 107 | /* Begin PBXProject section */ 108 | 4513D3CC21D5334D0070A7A5 /* Project object */ = { 109 | isa = PBXProject; 110 | attributes = { 111 | LastSwiftUpdateCheck = 1010; 112 | LastUpgradeCheck = 1100; 113 | TargetAttributes = { 114 | 4513D3E121D533BE0070A7A5 = { 115 | CreatedOnToolsVersion = 10.1; 116 | LastSwiftMigration = 1100; 117 | SystemCapabilities = { 118 | com.apple.Sandbox = { 119 | enabled = 0; 120 | }; 121 | }; 122 | }; 123 | }; 124 | }; 125 | buildConfigurationList = 4513D3CF21D5334D0070A7A5 /* Build configuration list for PBXProject "EonilFSEventsDemoGUI" */; 126 | compatibilityVersion = "Xcode 9.3"; 127 | developmentRegion = en; 128 | hasScannedForEncodings = 0; 129 | knownRegions = ( 130 | en, 131 | Base, 132 | ); 133 | mainGroup = 4513D3CB21D5334D0070A7A5; 134 | productRefGroup = 4513D3D721D533B20070A7A5 /* Products */; 135 | projectDirPath = ""; 136 | projectRoot = ""; 137 | targets = ( 138 | 4513D3E121D533BE0070A7A5 /* EonilFSEventsDemoGUI */, 139 | ); 140 | }; 141 | /* End PBXProject section */ 142 | 143 | /* Begin PBXResourcesBuildPhase section */ 144 | 4513D3E021D533BE0070A7A5 /* Resources */ = { 145 | isa = PBXResourcesBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | 4513D3E921D533C00070A7A5 /* Assets.xcassets in Resources */, 149 | 4513D3EC21D533C00070A7A5 /* Main.storyboard in Resources */, 150 | ); 151 | runOnlyForDeploymentPostprocessing = 0; 152 | }; 153 | /* End PBXResourcesBuildPhase section */ 154 | 155 | /* Begin PBXSourcesBuildPhase section */ 156 | 4513D3DE21D533BE0070A7A5 /* Sources */ = { 157 | isa = PBXSourcesBuildPhase; 158 | buildActionMask = 2147483647; 159 | files = ( 160 | 4513D3E721D533BE0070A7A5 /* ViewController.swift in Sources */, 161 | 4513D3E521D533BE0070A7A5 /* AppDelegate.swift in Sources */, 162 | ); 163 | runOnlyForDeploymentPostprocessing = 0; 164 | }; 165 | /* End PBXSourcesBuildPhase section */ 166 | 167 | /* Begin PBXVariantGroup section */ 168 | 4513D3EA21D533C00070A7A5 /* Main.storyboard */ = { 169 | isa = PBXVariantGroup; 170 | children = ( 171 | 4513D3EB21D533C00070A7A5 /* Base */, 172 | ); 173 | name = Main.storyboard; 174 | sourceTree = ""; 175 | }; 176 | /* End PBXVariantGroup section */ 177 | 178 | /* Begin XCBuildConfiguration section */ 179 | 4513D3D021D5334D0070A7A5 /* Debug */ = { 180 | isa = XCBuildConfiguration; 181 | buildSettings = { 182 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 183 | CLANG_WARN_BOOL_CONVERSION = YES; 184 | CLANG_WARN_COMMA = YES; 185 | CLANG_WARN_CONSTANT_CONVERSION = YES; 186 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 187 | CLANG_WARN_EMPTY_BODY = YES; 188 | CLANG_WARN_ENUM_CONVERSION = YES; 189 | CLANG_WARN_INFINITE_RECURSION = YES; 190 | CLANG_WARN_INT_CONVERSION = YES; 191 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 192 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 193 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 194 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 195 | CLANG_WARN_STRICT_PROTOTYPES = YES; 196 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 197 | CLANG_WARN_UNREACHABLE_CODE = YES; 198 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 199 | ENABLE_STRICT_OBJC_MSGSEND = YES; 200 | ENABLE_TESTABILITY = YES; 201 | GCC_NO_COMMON_BLOCKS = YES; 202 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 203 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 204 | GCC_WARN_UNDECLARED_SELECTOR = YES; 205 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 206 | GCC_WARN_UNUSED_FUNCTION = YES; 207 | GCC_WARN_UNUSED_VARIABLE = YES; 208 | ONLY_ACTIVE_ARCH = YES; 209 | }; 210 | name = Debug; 211 | }; 212 | 4513D3D121D5334D0070A7A5 /* Release */ = { 213 | isa = XCBuildConfiguration; 214 | buildSettings = { 215 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 216 | CLANG_WARN_BOOL_CONVERSION = YES; 217 | CLANG_WARN_COMMA = YES; 218 | CLANG_WARN_CONSTANT_CONVERSION = YES; 219 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 220 | CLANG_WARN_EMPTY_BODY = YES; 221 | CLANG_WARN_ENUM_CONVERSION = YES; 222 | CLANG_WARN_INFINITE_RECURSION = YES; 223 | CLANG_WARN_INT_CONVERSION = YES; 224 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 225 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 226 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 227 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 228 | CLANG_WARN_STRICT_PROTOTYPES = YES; 229 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 230 | CLANG_WARN_UNREACHABLE_CODE = YES; 231 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 232 | ENABLE_STRICT_OBJC_MSGSEND = YES; 233 | GCC_NO_COMMON_BLOCKS = YES; 234 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 235 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 236 | GCC_WARN_UNDECLARED_SELECTOR = YES; 237 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 238 | GCC_WARN_UNUSED_FUNCTION = YES; 239 | GCC_WARN_UNUSED_VARIABLE = YES; 240 | }; 241 | name = Release; 242 | }; 243 | 4513D40621D533C00070A7A5 /* Debug */ = { 244 | isa = XCBuildConfiguration; 245 | buildSettings = { 246 | ALWAYS_SEARCH_USER_PATHS = NO; 247 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 248 | CLANG_ANALYZER_NONNULL = YES; 249 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 250 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 251 | CLANG_CXX_LIBRARY = "libc++"; 252 | CLANG_ENABLE_MODULES = YES; 253 | CLANG_ENABLE_OBJC_ARC = YES; 254 | CLANG_ENABLE_OBJC_WEAK = YES; 255 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 256 | CLANG_WARN_BOOL_CONVERSION = YES; 257 | CLANG_WARN_COMMA = YES; 258 | CLANG_WARN_CONSTANT_CONVERSION = YES; 259 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 260 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 261 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 262 | CLANG_WARN_EMPTY_BODY = YES; 263 | CLANG_WARN_ENUM_CONVERSION = YES; 264 | CLANG_WARN_INFINITE_RECURSION = YES; 265 | CLANG_WARN_INT_CONVERSION = YES; 266 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 267 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 268 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 269 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 270 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 271 | CLANG_WARN_STRICT_PROTOTYPES = YES; 272 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 273 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 274 | CLANG_WARN_UNREACHABLE_CODE = YES; 275 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 276 | CODE_SIGN_STYLE = Manual; 277 | COMBINE_HIDPI_IMAGES = YES; 278 | COPY_PHASE_STRIP = NO; 279 | DEBUG_INFORMATION_FORMAT = dwarf; 280 | ENABLE_STRICT_OBJC_MSGSEND = YES; 281 | ENABLE_TESTABILITY = YES; 282 | GCC_C_LANGUAGE_STANDARD = gnu11; 283 | GCC_DYNAMIC_NO_PIC = NO; 284 | GCC_NO_COMMON_BLOCKS = YES; 285 | GCC_OPTIMIZATION_LEVEL = 0; 286 | GCC_PREPROCESSOR_DEFINITIONS = ( 287 | "DEBUG=1", 288 | "$(inherited)", 289 | ); 290 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 291 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 292 | GCC_WARN_UNDECLARED_SELECTOR = YES; 293 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 294 | GCC_WARN_UNUSED_FUNCTION = YES; 295 | GCC_WARN_UNUSED_VARIABLE = YES; 296 | INFOPLIST_FILE = EonilFSEventsDemoGUI/Info.plist; 297 | LD_RUNPATH_SEARCH_PATHS = ( 298 | "$(inherited)", 299 | "@executable_path/../Frameworks", 300 | ); 301 | MACOSX_DEPLOYMENT_TARGET = 10.14; 302 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 303 | MTL_FAST_MATH = YES; 304 | ONLY_ACTIVE_ARCH = YES; 305 | PRODUCT_BUNDLE_IDENTIFIER = Eonil.FSEventsDemoGUI; 306 | PRODUCT_NAME = "$(TARGET_NAME)"; 307 | SDKROOT = macosx; 308 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 309 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 310 | SWIFT_VERSION = 5.0; 311 | }; 312 | name = Debug; 313 | }; 314 | 4513D40721D533C00070A7A5 /* Release */ = { 315 | isa = XCBuildConfiguration; 316 | buildSettings = { 317 | ALWAYS_SEARCH_USER_PATHS = NO; 318 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 319 | CLANG_ANALYZER_NONNULL = YES; 320 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 321 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 322 | CLANG_CXX_LIBRARY = "libc++"; 323 | CLANG_ENABLE_MODULES = YES; 324 | CLANG_ENABLE_OBJC_ARC = YES; 325 | CLANG_ENABLE_OBJC_WEAK = YES; 326 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 327 | CLANG_WARN_BOOL_CONVERSION = YES; 328 | CLANG_WARN_COMMA = YES; 329 | CLANG_WARN_CONSTANT_CONVERSION = YES; 330 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 331 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 332 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 333 | CLANG_WARN_EMPTY_BODY = YES; 334 | CLANG_WARN_ENUM_CONVERSION = YES; 335 | CLANG_WARN_INFINITE_RECURSION = YES; 336 | CLANG_WARN_INT_CONVERSION = YES; 337 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 338 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 339 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 340 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 341 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 342 | CLANG_WARN_STRICT_PROTOTYPES = YES; 343 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 344 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 345 | CLANG_WARN_UNREACHABLE_CODE = YES; 346 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 347 | CODE_SIGN_STYLE = Manual; 348 | COMBINE_HIDPI_IMAGES = YES; 349 | COPY_PHASE_STRIP = NO; 350 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 351 | ENABLE_NS_ASSERTIONS = NO; 352 | ENABLE_STRICT_OBJC_MSGSEND = YES; 353 | GCC_C_LANGUAGE_STANDARD = gnu11; 354 | GCC_NO_COMMON_BLOCKS = YES; 355 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 356 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 357 | GCC_WARN_UNDECLARED_SELECTOR = YES; 358 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 359 | GCC_WARN_UNUSED_FUNCTION = YES; 360 | GCC_WARN_UNUSED_VARIABLE = YES; 361 | INFOPLIST_FILE = EonilFSEventsDemoGUI/Info.plist; 362 | LD_RUNPATH_SEARCH_PATHS = ( 363 | "$(inherited)", 364 | "@executable_path/../Frameworks", 365 | ); 366 | MACOSX_DEPLOYMENT_TARGET = 10.14; 367 | MTL_ENABLE_DEBUG_INFO = NO; 368 | MTL_FAST_MATH = YES; 369 | PRODUCT_BUNDLE_IDENTIFIER = Eonil.FSEventsDemoGUI; 370 | PRODUCT_NAME = "$(TARGET_NAME)"; 371 | SDKROOT = macosx; 372 | SWIFT_COMPILATION_MODE = wholemodule; 373 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 374 | SWIFT_VERSION = 5.0; 375 | }; 376 | name = Release; 377 | }; 378 | /* End XCBuildConfiguration section */ 379 | 380 | /* Begin XCConfigurationList section */ 381 | 4513D3CF21D5334D0070A7A5 /* Build configuration list for PBXProject "EonilFSEventsDemoGUI" */ = { 382 | isa = XCConfigurationList; 383 | buildConfigurations = ( 384 | 4513D3D021D5334D0070A7A5 /* Debug */, 385 | 4513D3D121D5334D0070A7A5 /* Release */, 386 | ); 387 | defaultConfigurationIsVisible = 0; 388 | defaultConfigurationName = Release; 389 | }; 390 | 4513D40521D533C00070A7A5 /* Build configuration list for PBXNativeTarget "EonilFSEventsDemoGUI" */ = { 391 | isa = XCConfigurationList; 392 | buildConfigurations = ( 393 | 4513D40621D533C00070A7A5 /* Debug */, 394 | 4513D40721D533C00070A7A5 /* Release */, 395 | ); 396 | defaultConfigurationIsVisible = 0; 397 | defaultConfigurationName = Release; 398 | }; 399 | /* End XCConfigurationList section */ 400 | 401 | /* Begin XCSwiftPackageProductDependency section */ 402 | BA53C7BA232B904E00838304 /* EonilFSEvents */ = { 403 | isa = XCSwiftPackageProductDependency; 404 | productName = EonilFSEvents; 405 | }; 406 | /* End XCSwiftPackageProductDependency section */ 407 | }; 408 | rootObject = 4513D3CC21D5334D0070A7A5 /* Project object */; 409 | } 410 | -------------------------------------------------------------------------------- /EonilFSEventsDemoGUI/EonilFSEventsDemoGUI.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /EonilFSEventsDemoGUI/EonilFSEventsDemoGUI.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /EonilFSEventsDemoGUI/EonilFSEventsDemoGUI.xcodeproj/xcshareddata/xcschemes/EonilFSEventsDemoGUI.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // EonilFSEventsDemoGUI 4 | // 5 | // Created by Henry on 2018/12/27. 6 | // 7 | 8 | import Cocoa 9 | 10 | @NSApplicationMain 11 | class AppDelegate: NSObject, NSApplicationDelegate {} 12 | 13 | -------------------------------------------------------------------------------- /EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | Default 530 | 531 | 532 | 533 | 534 | 535 | 536 | Left to Right 537 | 538 | 539 | 540 | 541 | 542 | 543 | Right to Left 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | Default 555 | 556 | 557 | 558 | 559 | 560 | 561 | Left to Right 562 | 563 | 564 | 565 | 566 | 567 | 568 | Right to Left 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 822 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | -------------------------------------------------------------------------------- /EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/EonilFSEventsDemoGUI.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSMainStoryboardFile 26 | Main 27 | NSPrincipalClass 28 | NSApplication 29 | 30 | 31 | -------------------------------------------------------------------------------- /EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // EonilFSEventsDemoGUI 4 | // 5 | // Created by Henry on 2018/12/27. 6 | // 7 | 8 | import Cocoa 9 | import EonilFSEvents 10 | 11 | class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate { 12 | 13 | private var items = [EonilFSEventsEvent]() 14 | private func process(fileSystemEvent e: EonilFSEventsEvent) { 15 | guard let v = tableView else { return } 16 | items.append(e) 17 | let a = v.numberOfRows 18 | let b = items.count 19 | let c = a.. Int { 48 | return items.count 49 | } 50 | func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { 51 | guard let c = tableColumn else { return nil } 52 | let v = tableView.makeView(withIdentifier: c.identifier, owner: self) as! NSTableCellView 53 | let item = items[row] 54 | v.identifier = c.identifier 55 | switch c.identifier { 56 | case nameTableColumn?.identifier: 57 | v.imageView?.image = NSWorkspace.shared.icon(forFile: item.path) 58 | v.textField?.stringValue = item.path 59 | case actionsTableColumn?.identifier: 60 | v.textField?.stringValue = item.flag?.description ?? "" 61 | default: 62 | break 63 | } 64 | return v 65 | } 66 | // func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? { 67 | // guard let tableColumn = tableColumn else { return nil } 68 | // let item = items[row] 69 | // switch tableColumn.identifier { 70 | // case nameTableColumn?.identifier: return item.path 71 | // case actionsTableColumn?.identifier: return item.flag 72 | // default: return nil 73 | // } 74 | // } 75 | } 76 | 77 | //extension EonilFSEventsEventFlags { 78 | // var description: String { 79 | // let all = [ 80 | // .historyDone: ".historyDone", 81 | // .idsWrapped: ".idsWrapped", 82 | // .itemChangeOwner: ".itemChangeOwner", 83 | // .itemCreated: ".itemCreated", 84 | // .itemFinderInfoMod: ".itemFinderInfoMod", 85 | // .itemInodeMetaMod: ".itemInodeMetaMod", 86 | // .itemIsDir: ".itemIsDir", 87 | // .itemIsFile: ".itemIsFile", 88 | // .itemIsHardlink: ".itemIsHardlink", 89 | // .itemIsLastHardlink: ".itemIsLastHardlink", 90 | // .itemIsSymlink: ".itemIsSymlink", 91 | // .itemModified: ".itemModified", 92 | // .itemRemoved: ".itemRemoved", 93 | // .itemRenamed: ".itemRenamed", 94 | // .itemXattrMod: ".itemXattrMod", 95 | // .kernelDropped: ".kernelDropped", 96 | // .mount: ".mount", 97 | // .mustScanSubDirs: ".mustScanSubDirs", 98 | // .none: ".none", 99 | // .ownEvent: ".ownEvent", 100 | // .rootChanged: ".rootChanged", 101 | // .unmount: ".unmount", 102 | // .userDropped: ".userDropped", 103 | // ] as [EonilFSEventsEventFlags: String] 104 | // var s = [String]() 105 | // for (k,n) in all { 106 | // if contains(k) { 107 | // s.append(n) 108 | // } 109 | // } 110 | // return s.joined(separator: ", ") 111 | // } 112 | //} 113 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Hoon H., Eonil 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.1 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "EonilFSEvents", 8 | platforms: [ 9 | .macOS(.v10_10), 10 | ], 11 | products: [ 12 | .library(name: "EonilFSEvents", targets: ["EonilFSEvents"]), 13 | .executable(name: "EonilFSEventsDemoCLI", targets: ["EonilFSEventsDemoCLI"]), 14 | ], 15 | dependencies: [ 16 | ], 17 | targets: [ 18 | .target(name: "EonilFSEvents", dependencies: []), 19 | .target(name: "EonilFSEventsDemoCLI", dependencies: ["EonilFSEvents"]), 20 | ] 21 | ) 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EonilFSEvents 2 | ============================= 3 | Eonil 4 | 2018 Maintenance. 5 | 2019 Maintenance. 6 | 7 | [![Build Status](https://api.travis-ci.org/eonil/FSEvents.svg)](https://travis-ci.org/eonil/FSEvents) 8 | 9 | It's possible to use FSEvents directly in Swift, but it still involves 10 | many boilerplate works and subtle conversions. 11 | 12 | This library provides mostly-faithful wrapper around FSEvents feature tailored 13 | for Swift 5. 14 | 15 | 16 | 17 | Quickstart 18 | ------------- 19 | Import. 20 | 21 | import EonilFSEvents 22 | 23 | Start. 24 | 25 | try EonilFSEvents.startWatching( 26 | paths: ["/"], 27 | for: ObjectIdentifier(self), 28 | with: { event in print(event) }) 29 | 30 | Stop. 31 | 32 | EonilFSEvents.stopWatching(for: ObjectIdentifier(self)) 33 | 34 | 35 | 36 | Using Full Features 37 | ----------------------- 38 | Make a `EonilFSEventStream`, schedule it to a GCD queue, and start. 39 | 40 | let s = try EonilFSEventStream(pathsToWatch: paths, 41 | sinceWhen: .now, 42 | latency: 0, 43 | flags: [], 44 | handler: handler) 45 | s.setDispatchQueue(DispatchQueue.main) 46 | try s.start() 47 | 48 | After use, deinitialize by stop, invalidate(unschedule). 49 | 50 | s.stop() 51 | s.invalidate() 52 | 53 | As soon as the last strong reference gets removed, 54 | the stream will be destroyed. 55 | 56 | 57 | 58 | Caveats 59 | ---------- 60 | In the Xcode, AppKit apps are configured to use Sandbox by default. 61 | Sandboxed apps cannot access files out of its container. 62 | Therefore, it could look like it cannot receive file system events 63 | out of the container. To receive file system events out of 64 | container, you should turn off sandboxing. 65 | 66 | At this point, `xcodebuild` fails on dependency resolution for packages. 67 | I don't know why. It seems Xcode have some issues with it. 68 | To work around, just set `SYMROOT` explicitly. 69 | See `test.zsh` how to set it. 70 | 71 | 72 | 73 | Credits & License 74 | ------------------------ 75 | Copyright(c) 2018 Hoon H., Eonil. 76 | All rights reserved. 77 | Use of this library is granted under "MIT License". 78 | -------------------------------------------------------------------------------- /Sources/EonilFSEvents/EonilFSEventStream.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EonilFSEventStream.swift 3 | // FSEventStreamWrapper 4 | // 5 | // Created by Hoon H. on 2016/10/02. 6 | // 7 | // 8 | 9 | import Foundation 10 | import CoreServices 11 | 12 | /// Replicate `FSEventStream`'s features and interface as close as possible in Swift-y interface. 13 | /// Apple can provide official wrapper in future release, and the name of the future wrapper type 14 | /// is likely to be `FSEventStream`. So this wrapper suffixes name with `~UnofficialWrapper` to avoid 15 | /// potential future name conflict. 16 | /// 17 | /// - TODO: Device watching support. 18 | /// 19 | public final class EonilFSEventStream { 20 | // This must be a non-nil value if an instance of this class has been created successfully. 21 | fileprivate var rawref: FSEventStreamRef! 22 | private let handler: (EonilFSEventsEvent) -> () 23 | 24 | /* 25 | * FSEventStreamCreate() 26 | * 27 | * Discussion: 28 | * Creates a new FS event stream object with the given parameters. 29 | * In order to start receiving callbacks you must also call 30 | * FSEventStreamScheduleWithRunLoop() and FSEventStreamStart(). 31 | * 32 | * Parameters: 33 | * 34 | * allocator: 35 | * The CFAllocator to be used to allocate memory for the stream. 36 | * Pass NULL or kCFAllocatorDefault to use the current default 37 | * allocator. 38 | * 39 | * callback: 40 | * An FSEventStreamCallback which will be called when FS events 41 | * occur. 42 | * 43 | * context: 44 | * A pointer to the FSEventStreamContext structure the client 45 | * wants to associate with this stream. Its fields are copied out 46 | * into the stream itself so its memory can be released after the 47 | * stream is created. Passing NULL is allowed and has the same 48 | * effect as passing a structure whose fields are all set to zero. 49 | * 50 | * pathsToWatch: 51 | * A CFArray of CFStringRefs, each specifying a path to a 52 | * directory, signifying the root of a filesystem hierarchy to be 53 | * watched for modifications. 54 | * 55 | * sinceWhen: 56 | * The service will supply events that have happened after the 57 | * given event ID. To ask for events "since now" pass the constant 58 | * kFSEventStreamEventIdSinceNow. Often, clients will supply the 59 | * highest-numbered FSEventStreamEventId they have received in a 60 | * callback, which they can obtain via the 61 | * FSEventStreamGetLatestEventId() accessor. Do not pass zero for 62 | * sinceWhen, unless you want to receive events for every 63 | * directory modified since "the beginning of time" -- an unlikely 64 | * scenario. 65 | * 66 | * latency: 67 | * The number of seconds the service should wait after hearing 68 | * about an event from the kernel before passing it along to the 69 | * client via its callback. Specifying a larger value may result 70 | * in more effective temporal coalescing, resulting in fewer 71 | * callbacks and greater overall efficiency. 72 | * 73 | * flags: 74 | * Flags that modify the behavior of the stream being created. See 75 | * FSEventStreamCreateFlags. 76 | * 77 | * Result: 78 | * A valid FSEventStreamRef. 79 | * 80 | * Availability: 81 | * Mac OS X: in version 10.5 and later in CoreServices.framework 82 | * CarbonLib: not available 83 | * Non-Carbon CFM: not available 84 | */ 85 | public init(pathsToWatch: [String], sinceWhen: EonilFSEventsEventID, latency: TimeInterval, flags: EonilFSEventsCreateFlags, handler: @escaping (EonilFSEventsEvent) -> ()) throws { 86 | // `CoreServices.FSEventStreamCallback` is C callback and follows 87 | // C convention. Which means it cannot capture any external value. 88 | let callback: CoreServices.FSEventStreamCallback = { ( 89 | _ streamRef: ConstFSEventStreamRef, 90 | _ clientCallBackInfo: UnsafeMutableRawPointer?, 91 | _ numEvents: Int, 92 | _ eventPaths: UnsafeMutableRawPointer, 93 | _ eventFlags: UnsafePointer, 94 | _ eventIds: UnsafePointer) -> () in 95 | guard let clientCallBackInfo1 = clientCallBackInfo else { 96 | EonilFSEventsIllogicalErrorLog(code: .missingContextRawPointerValue).cast() 97 | return 98 | } 99 | let eventPaths1: CFArray = Unmanaged.fromOpaque(eventPaths).takeUnretainedValue() 100 | guard let eventPaths2 = eventPaths1 as NSArray as? [NSString] as [String]? else { 101 | EonilFSEventsIllogicalErrorLog(code: .unexpectedPathValueType, message: "Cannot convert `\(eventPaths1)` into [String].").cast() 102 | return 103 | } 104 | guard numEvents == eventPaths2.count else { 105 | EonilFSEventsIllogicalErrorLog(code: .unmatchedEventParameterCounts, message: "Event count is `\(numEvents)`, but path count is `\(eventPaths2.count)`").cast() 106 | return 107 | } 108 | let unmanagedPtr: Unmanaged = Unmanaged.fromOpaque(clientCallBackInfo1) 109 | let self1 = unmanagedPtr.takeUnretainedValue() 110 | for i in 0..(value: UnsafeMutablePointer) -> UnsafeMutablePointer { 130 | return value 131 | } 132 | // Get pointer to a value on stack. 133 | // Stream creation function will copy the value, so it's safe to keep it 134 | // on stack. 135 | let context1: UnsafeMutablePointer? = getPtr(value: &context) 136 | let pathsToWatch1: CFArray = pathsToWatch as [NSString] as NSArray as CFArray 137 | let sinceWhen1: FSEventStreamEventId = sinceWhen.rawValue 138 | let latency1: CFTimeInterval = latency as CFTimeInterval 139 | // Always use CF types to avoid copying cost. But I am pretty sure that this 140 | // ultimately trigger copying inside of the system framework... 141 | let flags1: FSEventStreamCreateFlags = flags.union(.useCFTypes).rawValue 142 | guard let newRawref = FSEventStreamCreate(nil, callback, context1, pathsToWatch1, sinceWhen1, latency1, flags1) else { 143 | throw EonilFSEventsError(code: .cannotCreateStream) 144 | } 145 | rawref = newRawref 146 | } 147 | deinit { 148 | // It seems `rawref` does not get deallocated according to Instruments: 149 | // Run EonilFSEventsDemoGUI via Instruments with "Leaks" and close the main window. 150 | FSEventStreamRelease(self.rawref) 151 | } 152 | } 153 | 154 | /* 155 | * Accessors 156 | */ 157 | extension EonilFSEventStream { 158 | /* 159 | * FSEventStreamGetLatestEventId() 160 | * 161 | * Discussion: 162 | * Fetches the sinceWhen property of the stream. Upon receiving an 163 | * event (and just before invoking the client's callback) this 164 | * attribute is updated to the highest-numbered event ID mentioned 165 | * in the event. 166 | * 167 | * Parameters: 168 | * 169 | * streamRef: 170 | * A valid stream. 171 | * 172 | * Result: 173 | * The sinceWhen attribute of the stream. 174 | * 175 | * Availability: 176 | * Mac OS X: in version 10.5 and later in CoreServices.framework 177 | * CarbonLib: not available 178 | * Non-Carbon CFM: not available 179 | */ 180 | 181 | @available(macOS, introduced: 10.5) 182 | @available(iOS, introduced: 6.0) 183 | public func getLatestEventID() -> EonilFSEventsEventID { 184 | let eventId = FSEventStreamGetLatestEventId(rawref) 185 | let eventID1 = EonilFSEventsEventID(rawValue: eventId) 186 | return eventID1 187 | } 188 | 189 | 190 | // /* 191 | // * FSEventStreamGetDeviceBeingWatched() 192 | // * 193 | // * Discussion: 194 | // * Fetches the dev_t supplied when the stream was created via 195 | // * FSEventStreamCreateRelativeToDevice(), otherwise 0. 196 | // * 197 | // * Parameters: 198 | // * 199 | // * streamRef: 200 | // * A valid stream. 201 | // * 202 | // * Result: 203 | // * The dev_t for a device-relative stream, otherwise 0. 204 | // * 205 | // * Availability: 206 | // * Mac OS X: in version 10.5 and later in CoreServices.framework 207 | // * CarbonLib: not available 208 | // * Non-Carbon CFM: not available 209 | // */ 210 | // @available(macOS, introduced: 10.5) 211 | // @available(iOS, introduced: 6.0) 212 | // public func getDeviceBeingWatched() -> dev_t { 213 | // return FSEventStreamGetDeviceBeingWatched(rawref) 214 | // } 215 | 216 | /* 217 | * FSEventStreamCopyPathsBeingWatched() 218 | * 219 | * Discussion: 220 | * Fetches the paths supplied when the stream was created via one of 221 | * the FSEventStreamCreate...() functions. 222 | * 223 | * Parameters: 224 | * 225 | * streamRef: 226 | * A valid stream. 227 | * 228 | * Result: 229 | * A CFArray of CFStringRefs corresponding to those supplied when 230 | * the stream was created. Ownership follows the Copy rule. 231 | * 232 | * Availability: 233 | * Mac OS X: in version 10.5 and later in CoreServices.framework 234 | * CarbonLib: not available 235 | * Non-Carbon CFM: not available 236 | */ 237 | @available(macOS, introduced: 10.5) 238 | @available(iOS, introduced: 6.0) 239 | public func copyPathsBeingWatched() -> [String] { 240 | let ret = FSEventStreamCopyPathsBeingWatched(rawref) 241 | guard let paths = ret as NSArray as? [NSString] as [String]? else { 242 | EonilFSEventsIllogicalErrorLog(code: .unexpectedPathValueType, message: "Cannot convert retrieved object `\(ret)` into `[String]`.").cast() 243 | // Unrecoverable. 244 | fatalError() 245 | } 246 | return paths 247 | } 248 | 249 | // /* 250 | // * FSEventsCopyUUIDForDevice() 251 | // * 252 | // * Discussion: 253 | // * Gets the UUID associated with a device, or NULL if not possible 254 | // * (for example, on read-only device). A (non-NULL) UUID uniquely 255 | // * identifies a given stream of FSEvents. If this (non-NULL) UUID 256 | // * is different than one that you stored from a previous run then 257 | // * the event stream is different (for example, because FSEvents were 258 | // * purged, because the disk was erased, or because the event ID 259 | // * counter wrapped around back to zero). A NULL return value 260 | // * indicates that "historical" events are not available, i.e., you 261 | // * should not supply a "sinceWhen" value to FSEventStreamCreate...() 262 | // * other than kFSEventStreamEventIdSinceNow. 263 | // * 264 | // * Parameters: 265 | // * 266 | // * dev: 267 | // * The dev_t of the device that you want to get the UUID for. 268 | // * 269 | // * Result: 270 | // * The UUID associated with the stream of events on this device, or 271 | // * NULL if no UUID is available (for example, on a read-only 272 | // * device). The UUID is stored on the device itself and travels 273 | // * with it even when the device is attached to different computers. 274 | // * Ownership follows the Copy Rule. 275 | // * 276 | // * Availability: 277 | // * Mac OS X: in version 10.5 and later in CoreServices.framework 278 | // * CarbonLib: not available 279 | // * Non-Carbon CFM: not available 280 | // */ 281 | // extern CF_RETURNS_RETAINED CFUUIDRef __nullable 282 | // FSEventsCopyUUIDForDevice(dev_t dev) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_6_0); 283 | 284 | // /* 285 | // * FSEventsGetLastEventIdForDeviceBeforeTime() 286 | // * 287 | // * Discussion: 288 | // * Gets the last event ID for the given device that was returned 289 | // * before the given time. This is conservative in the sense that if 290 | // * you then use the returned event ID as the sinceWhen parameter of 291 | // * FSEventStreamCreateRelativeToDevice() that you will not miss any 292 | // * events that happened since that time. On the other hand, you 293 | // * might receive some (harmless) extra events. Beware: there are 294 | // * things that can cause this to fail to be accurate. For example, 295 | // * someone might change the system's clock (either backwards or 296 | // * forwards). Or an external drive might be used on different 297 | // * systems without perfectly synchronized clocks. 298 | // * 299 | // * Parameters: 300 | // * 301 | // * dev: 302 | // * The dev_t of the device. 303 | // * 304 | // * time: 305 | // * The time as a CFAbsoluteTime whose value is the number of 306 | // * seconds since Jan 1, 1970 (i.e. a posix style time_t). 307 | // * 308 | // * Result: 309 | // * The last event ID for the given device that was returned before 310 | // * the given time. 311 | // * 312 | // * Availability: 313 | // * Mac OS X: in version 10.5 and later in CoreServices.framework 314 | // * CarbonLib: not available 315 | // * Non-Carbon CFM: not available 316 | // */ 317 | // extern FSEventStreamEventId 318 | // FSEventsGetLastEventIdForDeviceBeforeTime( 319 | // dev_t dev, 320 | // CFAbsoluteTime time) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_6_0); 321 | 322 | // /* 323 | // * FSEventsPurgeEventsForDeviceUpToEventId() 324 | // * 325 | // * Discussion: 326 | // * Purges old events from the persistent per-volume database 327 | // * maintained by the service. Can only be called by the root user. 328 | // * 329 | // * Parameters: 330 | // * 331 | // * dev: 332 | // * The dev_t of the device. 333 | // * 334 | // * eventId: 335 | // * The event ID. 336 | // * 337 | // * Result: 338 | // * True if it succeeds, otherwise False if it fails. 339 | // * 340 | // * Availability: 341 | // * Mac OS X: in version 10.5 and later in CoreServices.framework 342 | // * CarbonLib: not available 343 | // * Non-Carbon CFM: not available 344 | // */ 345 | // extern Boolean 346 | // FSEventsPurgeEventsForDeviceUpToEventId( 347 | // dev_t dev, 348 | // FSEventStreamEventId eventId) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_6_0); 349 | 350 | } 351 | 352 | /* 353 | * ScheduleWithRunLoop, UnscheduleFromRunLoop, Invalidate 354 | */ 355 | extension EonilFSEventStream { 356 | /* 357 | * FSEventStreamScheduleWithRunLoop() 358 | * 359 | * Discussion: 360 | * This function schedules the stream on the specified run loop, 361 | * like CFRunLoopAddSource() does for a CFRunLoopSourceRef. The 362 | * caller is responsible for ensuring that the stream is scheduled 363 | * on at least one run loop and that at least one of the run loops 364 | * on which the stream is scheduled is being run. To start receiving 365 | * events on the stream, call FSEventStreamStart(). To remove the 366 | * stream from the run loops upon which it has been scheduled, call 367 | * FSEventStreamUnscheduleFromRunLoop() or FSEventStreamInvalidate(). 368 | * 369 | * Parameters: 370 | * 371 | * streamRef: 372 | * A valid stream. 373 | * 374 | * runLoop: 375 | * The run loop on which to schedule the stream. 376 | * 377 | * runLoopMode: 378 | * A run loop mode on which to schedule the stream. 379 | * 380 | * Availability: 381 | * Mac OS X: in version 10.5 and later in CoreServices.framework 382 | * CarbonLib: not available 383 | * Non-Carbon CFM: not available 384 | */ 385 | @available(OSX 10.5, *) 386 | public func scheduleWithRunloop(runLoop: RunLoop, runLoopMode: RunLoop.Mode) { 387 | let runLoopMode1 = runLoopMode as CFString 388 | FSEventStreamScheduleWithRunLoop(rawref, runLoop.getCFRunLoop(), runLoopMode1) 389 | } 390 | 391 | /* 392 | * FSEventStreamUnscheduleFromRunLoop() 393 | * 394 | * Discussion: 395 | * This function removes the stream from the specified run loop, 396 | * like CFRunLoopRemoveSource() does for a CFRunLoopSourceRef. 397 | * 398 | * Parameters: 399 | * 400 | * streamRef: 401 | * A valid stream. 402 | * 403 | * runLoop: 404 | * The run loop from which to unschedule the stream. 405 | * 406 | * runLoopMode: 407 | * The run loop mode from which to unschedule the stream. 408 | * 409 | * Availability: 410 | * Mac OS X: in version 10.5 and later in CoreServices.framework 411 | * CarbonLib: not available 412 | * Non-Carbon CFM: not available 413 | */ 414 | @available(OSX 10.5, *) 415 | public func unscheduleFromRunLoop(runLoop: RunLoop, runLoopMode: RunLoop.Mode) { 416 | let runLoopMode1 = runLoopMode as CFString 417 | FSEventStreamUnscheduleFromRunLoop(rawref, runLoop.getCFRunLoop(), runLoopMode1) 418 | } 419 | 420 | /* 421 | * FSEventStreamSetDispatchQueue() 422 | * 423 | * Discussion: 424 | * This function schedules the stream on the specified dispatch 425 | * queue. The caller is responsible for ensuring that the stream is 426 | * scheduled on a dispatch queue and that the queue is started. If 427 | * there is a problem scheduling the stream on the queue an error 428 | * will be returned when you try to Start the stream. To start 429 | * receiving events on the stream, call FSEventStreamStart(). To 430 | * remove the stream from the queue on which it was scheduled, call 431 | * FSEventStreamSetDispatchQueue() with a NULL queue parameter or 432 | * call FSEventStreamInvalidate() which will do the same thing. 433 | * Note: you must eventually call FSEventStreamInvalidate() and it 434 | * is an error to call FSEventStreamInvalidate() without having the 435 | * stream either scheduled on a runloop or a dispatch queue, so do 436 | * not set the dispatch queue to NULL before calling 437 | * FSEventStreamInvalidate(). 438 | * 439 | * Parameters: 440 | * 441 | * streamRef: 442 | * A valid stream. 443 | * 444 | * q: 445 | * The dispatch queue to use to receive events (or NULL to to stop 446 | * receiving events from the stream). 447 | * 448 | * Availability: 449 | * Mac OS X: in version 10.6 and later in CoreServices.framework 450 | * CarbonLib: not available 451 | * Non-Carbon CFM: not available 452 | */ 453 | @available(OSX 10.6, *) 454 | public func setDispatchQueue(_ q: DispatchQueue?) { 455 | FSEventStreamSetDispatchQueue(rawref, q) 456 | } 457 | 458 | /* 459 | * FSEventStreamInvalidate() 460 | * 461 | * Discussion: 462 | * Invalidates the stream, like CFRunLoopSourceInvalidate() does for 463 | * a CFRunLoopSourceRef. It will be unscheduled from any runloops 464 | * or dispatch queues upon which it had been scheduled. 465 | * FSEventStreamInvalidate() can only be called on the stream after 466 | * you have called FSEventStreamScheduleWithRunLoop() or 467 | * FSEventStreamSetDispatchQueue(). 468 | * 469 | * Parameters: 470 | * 471 | * streamRef: 472 | * A valid stream. 473 | * 474 | * Availability: 475 | * Mac OS X: in version 10.5 and later in CoreServices.framework 476 | * CarbonLib: not available 477 | * Non-Carbon CFM: not available 478 | */ 479 | @available(OSX 10.5, *) 480 | public func invalidate() { 481 | FSEventStreamInvalidate(rawref) 482 | } 483 | } 484 | 485 | /* 486 | * Start, Flush, Stop 487 | */ 488 | extension EonilFSEventStream { 489 | /* 490 | * FSEventStreamStart() 491 | * 492 | * Discussion: 493 | * Attempts to register with the FS Events service to receive events 494 | * per the parameters in the stream. FSEventStreamStart() can only 495 | * be called once the stream has been scheduled on at least one 496 | * runloop, via FSEventStreamScheduleWithRunLoop(). Once started, 497 | * the stream can be stopped via FSEventStreamStop(). 498 | * 499 | * Parameters: 500 | * 501 | * streamRef: 502 | * A valid stream. 503 | * 504 | * Result: 505 | * True if it succeeds, otherwise False if it fails. It ought to 506 | * always succeed, but in the event it does not then your code 507 | * should fall back to performing recursive scans of the directories 508 | * of interest as appropriate. 509 | * 510 | * Availability: 511 | * Mac OS X: in version 10.5 and later in CoreServices.framework 512 | * CarbonLib: not available 513 | * Non-Carbon CFM: not available 514 | */ 515 | @available(OSX 10.5, *) 516 | public func start() throws { 517 | switch FSEventStreamStart(rawref) { 518 | case false: 519 | throw EonilFSEventsError.init(code: .cannotStartStream) 520 | case true: 521 | return 522 | } 523 | } 524 | 525 | /* 526 | * FSEventStreamFlushAsync() 527 | * 528 | * Discussion: 529 | * Asks the FS Events service to flush out any events that have 530 | * occurred but have not yet been delivered, due to the latency 531 | * parameter that was supplied when the stream was created. This 532 | * flushing occurs asynchronously -- do not expect the events to 533 | * have already been delivered by the time this call returns. 534 | * FSEventStreamFlushAsync() can only be called after the stream has 535 | * been started, via FSEventStreamStart(). 536 | * 537 | * Parameters: 538 | * 539 | * streamRef: 540 | * A valid stream. 541 | * 542 | * Result: 543 | * The largest event id of any event ever queued for this stream, 544 | * otherwise zero if no events have been queued for this stream. 545 | * 546 | * Availability: 547 | * Mac OS X: in version 10.5 and later in CoreServices.framework 548 | * CarbonLib: not available 549 | * Non-Carbon CFM: not available 550 | */ 551 | @available(OSX 10.5, *) 552 | public func flushAsync() -> EonilFSEventsEventID { 553 | let eventId = FSEventStreamFlushAsync(rawref) 554 | let eventId1 = EonilFSEventsEventID(rawValue: eventId) 555 | return eventId1 556 | } 557 | 558 | /* 559 | * FSEventStreamFlushSync() 560 | * 561 | * Discussion: 562 | * Asks the FS Events service to flush out any events that have 563 | * occurred but have not yet been delivered, due to the latency 564 | * parameter that was supplied when the stream was created. This 565 | * flushing occurs synchronously -- by the time this call returns, 566 | * your callback will have been invoked for every event that had 567 | * already occurred at the time you made this call. 568 | * FSEventStreamFlushSync() can only be called after the stream has 569 | * been started, via FSEventStreamStart(). 570 | * 571 | * Parameters: 572 | * 573 | * streamRef: 574 | * A valid stream. 575 | * 576 | * Availability: 577 | * Mac OS X: in version 10.5 and later in CoreServices.framework 578 | * CarbonLib: not available 579 | * Non-Carbon CFM: not available 580 | */ 581 | @available(OSX 10.5, *) 582 | public func flushSync() { 583 | FSEventStreamFlushSync(rawref) 584 | } 585 | 586 | /* 587 | * FSEventStreamStop() 588 | * 589 | * Discussion: 590 | * Unregisters with the FS Events service. The client callback will 591 | * not be called for this stream while it is stopped. 592 | * FSEventStreamStop() can only be called if the stream has been 593 | * started, via FSEventStreamStart(). Once stopped, the stream can 594 | * be restarted via FSEventStreamStart(), at which point it will 595 | * resume receiving events from where it left off ("sinceWhen"). 596 | * 597 | * Parameters: 598 | * 599 | * streamRef: 600 | * A valid stream. 601 | * 602 | * Availability: 603 | * Mac OS X: in version 10.5 and later in CoreServices.framework 604 | * CarbonLib: not available 605 | * Non-Carbon CFM: not available 606 | */ 607 | @available(OSX 10.5, *) 608 | public func stop() { 609 | FSEventStreamStop(rawref) 610 | } 611 | } 612 | 613 | /* 614 | * Debugging 615 | */ 616 | extension EonilFSEventStream { 617 | /* 618 | * FSEventStreamShow() 619 | * 620 | * Discussion: 621 | * Prints a description of the supplied stream to stderr. For 622 | * debugging only. 623 | * 624 | * Parameters: 625 | * 626 | * streamRef: 627 | * A valid stream. 628 | * 629 | * Availability: 630 | * Mac OS X: in version 10.5 and later in CoreServices.framework 631 | * CarbonLib: not available 632 | * Non-Carbon CFM: not available 633 | */ 634 | @available(OSX 10.5, *) 635 | private func show() { 636 | FSEventStreamShow(rawref) 637 | } 638 | 639 | /* 640 | * FSEventStreamCopyDescription() 641 | * 642 | * Discussion: 643 | * Returns a CFStringRef containing the description of the supplied 644 | * stream. For debugging only. 645 | * 646 | * Result: 647 | * A CFStringRef containing the description of the supplied stream. 648 | * Ownership follows the Copy rule. 649 | * 650 | * Availability: 651 | * Mac OS X: in version 10.5 and later in CoreServices.framework 652 | * CarbonLib: not available 653 | * Non-Carbon CFM: not available 654 | */ 655 | @available(OSX 10.5, *) 656 | fileprivate func copyDescription() -> String { 657 | let desc = FSEventStreamCopyDescription(rawref) 658 | let desc1 = desc as String 659 | return desc1 660 | } 661 | 662 | /* 663 | * FSEventStreamSetExclusionPaths() 664 | * 665 | * Discussion: 666 | * Sets directories to be filtered from the EventStream. 667 | * A maximum of 8 directories maybe specified. 668 | * 669 | * Result: 670 | * True if it succeeds, otherwise False if it fails. 671 | * 672 | * Availability: 673 | * Mac OS X: in version 10.9 and later in CoreServices.framework 674 | * CarbonLib: not available 675 | * Non-Carbon CFM: not available 676 | */ 677 | @available(OSX 10.9, *) 678 | @discardableResult 679 | public func setExclusionPaths(_ pathsToExclude: [String]) -> Bool { 680 | let pathsToExclude1 = pathsToExclude as [NSString] as NSArray as CFArray 681 | return FSEventStreamSetExclusionPaths(rawref, pathsToExclude1) 682 | } 683 | } 684 | extension EonilFSEventStream: CustomStringConvertible, CustomDebugStringConvertible { 685 | public var description: String { 686 | return copyDescription() 687 | } 688 | public var debugDescription: String { 689 | return copyDescription() 690 | } 691 | } 692 | 693 | 694 | -------------------------------------------------------------------------------- /Sources/EonilFSEvents/EonilFSEventStreamCreateFlags.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EonilFSEventsCreateFlags.swift 3 | // EonilFSEvents 4 | // 5 | // Created by Hoon H. on 2016/10/02. 6 | // 7 | // 8 | 9 | import Foundation 10 | import CoreServices 11 | 12 | public struct EonilFSEventsCreateFlags: OptionSet { 13 | public let rawValue: FSEventStreamCreateFlags 14 | public init(rawValue: FSEventStreamCreateFlags) { 15 | self.rawValue = rawValue 16 | } 17 | fileprivate init(rawValue: Int) { 18 | self.rawValue = FSEventStreamCreateFlags(truncatingIfNeeded: rawValue) 19 | } 20 | } 21 | 22 | /// Flags that can be passed to `EonilFSEvents.init` 23 | /// to modify the behavior of the stream being created. 24 | /// 25 | /// - Note: 26 | /// Documentation comments are copied from Apple's documentation 27 | /// for convenience. 28 | /// 29 | /// - Note: 30 | /// `kFSEventStreamCreateFlagUseCFTypes` is not available because 31 | /// this wrapper designed to be Swift-y interface as much as possible 32 | /// by sacrificing a bit of performance. 33 | /// 34 | public extension EonilFSEventsCreateFlags { 35 | 36 | /* 37 | * The default. 38 | */ 39 | static var none: EonilFSEventsCreateFlags { 40 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagNone) 41 | } 42 | 43 | /* 44 | * The framework will invoke your callback function with CF types 45 | * rather than raw C types (i.e., a CFArrayRef of CFStringRefs, 46 | * rather than a raw C array of raw C string pointers). See 47 | * FSEventStreamCallback. 48 | */ 49 | internal static var useCFTypes: EonilFSEventsCreateFlags { 50 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagUseCFTypes) 51 | } 52 | 53 | /* 54 | * Affects the meaning of the latency parameter. If you specify this 55 | * flag and more than latency seconds have elapsed since the last 56 | * event, your app will receive the event immediately. The delivery 57 | * of the event resets the latency timer and any further events will 58 | * be delivered after latency seconds have elapsed. This flag is 59 | * useful for apps that are interactive and want to react immediately 60 | * to changes but avoid getting swamped by notifications when changes 61 | * are occurringin rapid succession. If you do not specify this flag, 62 | * then when an event occurs after a period of no events, the latency 63 | * timer is started. Any events that occur during the next latency 64 | * seconds will be delivered as one group (including that first 65 | * event). The delivery of the group of events resets the latency 66 | * timer and any further events will be delivered after latency 67 | * seconds. This is the default behavior and is more appropriate for 68 | * background, daemon or batch processing apps. 69 | */ 70 | static var noDefer: EonilFSEventsCreateFlags { 71 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagNoDefer) 72 | } 73 | 74 | /* 75 | * Request notifications of changes along the path to the path(s) 76 | * you're watching. For example, with this flag, if you watch 77 | * "/foo/bar" and it is renamed to "/foo/bar.old", you would receive 78 | * a RootChanged event. The same is true if the directory "/foo" were 79 | * renamed. The event you receive is a special event: the path for 80 | * the event is the original path you specified, the flag 81 | * kFSEventStreamEventFlagRootChanged is set and event ID is zero. 82 | * RootChanged events are useful to indicate that you should rescan a 83 | * particular hierarchy because it changed completely (as opposed to 84 | * the things inside of it changing). If you want to track the 85 | * current location of a directory, it is best to open the directory 86 | * before creating the stream so that you have a file descriptor for 87 | * it and can issue an F_GETPATH fcntl() to find the current path. 88 | */ 89 | static var watchRoot: EonilFSEventsCreateFlags { 90 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagWatchRoot) 91 | } 92 | 93 | /* 94 | * Don't send events that were triggered by the current process. This 95 | * is useful for reducing the volume of events that are sent. It is 96 | * only useful if your process might modify the file system hierarchy 97 | * beneath the path(s) being monitored. Note: this has no effect on 98 | * historical events, i.e., those delivered before the HistoryDone 99 | * sentinel event. Also, this does not apply to RootChanged events 100 | * because the WatchRoot feature uses a separate mechanism that is 101 | * unable to provide information about the responsible process. 102 | */ 103 | @available(macOS, introduced: 10.6) 104 | @available(iOS, introduced: 6.0) 105 | static var ignoreSelf: EonilFSEventsCreateFlags { 106 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagIgnoreSelf) 107 | } 108 | 109 | /* 110 | * Request file-level notifications. Your stream will receive events 111 | * about individual files in the hierarchy you're watching instead of 112 | * only receiving directory level notifications. Use this flag with 113 | * care as it will generate significantly more events than without it. 114 | */ 115 | @available(macOS, introduced: 10.7) 116 | @available(iOS, introduced: 6.0) 117 | static var fileEvents: EonilFSEventsCreateFlags { 118 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagFileEvents) 119 | } 120 | 121 | /* 122 | * Tag events that were triggered by the current process with the "OwnEvent" flag. 123 | * This is only useful if your process might modify the file system hierarchy 124 | * beneath the path(s) being monitored and you wish to know which events were 125 | * triggered by your process. Note: this has no effect on historical events, i.e., 126 | * those delivered before the HistoryDone sentinel event. 127 | */ 128 | @available(macOS, introduced: 10.9) 129 | @available(iOS, introduced: 7.0) 130 | static var markSelf: EonilFSEventsCreateFlags { 131 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagMarkSelf) 132 | } 133 | } 134 | //public enum EonilFSEventsCreateFlags: UInt32, OptionSet { 135 | //// public static let none = EonilFSEventsCreateFlags([]) 136 | // 137 | //// public init(rawValue: UInt32) { 138 | //// self = rawValue 139 | //// } 140 | // 141 | // /* 142 | // * The framework will invoke your callback function with CF types 143 | // * rather than raw C types (i.e., a CFArrayRef of CFStringRefs, 144 | // * rather than a raw C array of raw C string pointers). See 145 | // * FSEventStreamCallback. 146 | // */ 147 | // case useCFTypes = 0x00000001 148 | // 149 | // /* 150 | // * Affects the meaning of the latency parameter. If you specify this 151 | // * flag and more than latency seconds have elapsed since the last 152 | // * event, your app will receive the event immediately. The delivery 153 | // * of the event resets the latency timer and any further events will 154 | // * be delivered after latency seconds have elapsed. This flag is 155 | // * useful for apps that are interactive and want to react immediately 156 | // * to changes but avoid getting swamped by notifications when changes 157 | // * are occurringin rapid succession. If you do not specify this flag, 158 | // * then when an event occurs after a period of no events, the latency 159 | // * timer is started. Any events that occur during the next latency 160 | // * seconds will be delivered as one group (including that first 161 | // * event). The delivery of the group of events resets the latency 162 | // * timer and any further events will be delivered after latency 163 | // * seconds. This is the default behavior and is more appropriate for 164 | // * background, daemon or batch processing apps. 165 | // */ 166 | // case noDefer = 0x00000002 167 | // 168 | // /* 169 | // * Request notifications of changes along the path to the path(s) 170 | // * you're watching. For example, with this flag, if you watch 171 | // * "/foo/bar" and it is renamed to "/foo/bar.old", you would receive 172 | // * a RootChanged event. The same is true if the directory "/foo" were 173 | // * renamed. The event you receive is a special event: the path for 174 | // * the event is the original path you specified, the flag 175 | // * kFSEventStreamEventFlagRootChanged is set and event ID is zero. 176 | // * RootChanged events are useful to indicate that you should rescan a 177 | // * particular hierarchy because it changed completely (as opposed to 178 | // * the things inside of it changing). If you want to track the 179 | // * current location of a directory, it is best to open the directory 180 | // * before creating the stream so that you have a file descriptor for 181 | // * it and can issue an F_GETPATH fcntl() to find the current path. 182 | // */ 183 | // case watchRoot = 0x00000004 184 | // 185 | // /* 186 | // * Don't send events that were triggered by the current process. This 187 | // * is useful for reducing the volume of events that are sent. It is 188 | // * only useful if your process might modify the file system hierarchy 189 | // * beneath the path(s) being monitored. Note: this has no effect on 190 | // * historical events, i.e., those delivered before the HistoryDone 191 | // * sentinel event. Also, this does not apply to RootChanged events 192 | // * because the WatchRoot feature uses a separate mechanism that is 193 | // * unable to provide information about the responsible process. 194 | // */ 195 | // @available(macOS, introduced: 10.6) 196 | // @available(iOS, introduced: 6.0) 197 | // case ignoreSelf = 0x00000008 198 | // 199 | // /* 200 | // * Request file-level notifications. Your stream will receive events 201 | // * about individual files in the hierarchy you're watching instead of 202 | // * only receiving directory level notifications. Use this flag with 203 | // * care as it will generate significantly more events than without it. 204 | // */ 205 | // @available(macOS, introduced: 10.7) 206 | // @available(iOS, introduced: 6.0) 207 | // case fileEvents = 0x00000010 208 | // 209 | // /* 210 | // * Tag events that were triggered by the current process with the "OwnEvent" flag. 211 | // * This is only useful if your process might modify the file system hierarchy 212 | // * beneath the path(s) being monitored and you wish to know which events were 213 | // * triggered by your process. Note: this has no effect on historical events, i.e., 214 | // * those delivered before the HistoryDone sentinel event. 215 | // */ 216 | // @available(macOS, introduced: 10.9) 217 | // @available(iOS, introduced: 7.0) 218 | // case markSelf = 0x00000020 219 | //} 220 | 221 | extension EonilFSEventsCreateFlags: Hashable, CustomStringConvertible, CustomDebugStringConvertible { 222 | public var hashValue: Int { 223 | return rawValue.hashValue 224 | } 225 | private static func getNameMapping() -> [EonilFSEventsCreateFlags: String] { 226 | return [ 227 | .none: ".none", 228 | .useCFTypes: ".useCFTypes", 229 | .noDefer: ".noDefer", 230 | .watchRoot: ".watchRoot", 231 | .ignoreSelf: ".ignoreSelf", 232 | .fileEvents: ".fileEvents", 233 | .markSelf: ".markSelf", 234 | ] 235 | } 236 | public var description: String { 237 | return debugDescription 238 | } 239 | public var debugDescription: String { 240 | let map = EonilFSEventsCreateFlags.getNameMapping() 241 | let ns1 = map.filter({ contains($0.key) }).map({ $0.value }) 242 | return "[\(ns1.joined(separator: ","))]" 243 | } 244 | } 245 | 246 | -------------------------------------------------------------------------------- /Sources/EonilFSEvents/EonilFSEventStreamError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EonilFSEventsError.swift 3 | // EonilFSEvents 4 | // 5 | // Created by Hoon H. on 2016/10/02. 6 | // 7 | // 8 | 9 | public struct EonilFSEventsError: Error { 10 | public var code: EonilFSEventsErrorCode 11 | public var message: String? 12 | init(code: EonilFSEventsErrorCode) { 13 | self.code = code 14 | } 15 | init(code: EonilFSEventsErrorCode, message: String) { 16 | self.code = code 17 | self.message = message 18 | } 19 | } 20 | 21 | public enum EonilFSEventsErrorCode { 22 | case cannotCreateStream 23 | case cannotStartStream 24 | } 25 | -------------------------------------------------------------------------------- /Sources/EonilFSEvents/EonilFSEventStreamEvent.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EonilFSEventsEvent.swift 3 | // EonilFSEvents 4 | // 5 | // Created by Hoon H. on 2016/10/02. 6 | // 7 | // 8 | 9 | public struct EonilFSEventsEvent { 10 | public var path: String 11 | public var flag: EonilFSEventsEventFlags? 12 | public var ID: EonilFSEventsEventID? 13 | } 14 | -------------------------------------------------------------------------------- /Sources/EonilFSEvents/EonilFSEventStreamEventFlags.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EonilFSEventsEventFlags.swift 3 | // EonilFSEvents 4 | // 5 | // Created by Hoon H. on 2016/10/02. 6 | // 7 | // 8 | 9 | import Foundation 10 | import CoreServices 11 | 12 | /// Flags that can be passed to your `EonilFSEvents`'s handler function. 13 | /* 14 | * FSEventStreamEventFlags 15 | * 16 | * Discussion: 17 | * Flags that can be passed to your FSEventStreamCallback function. 18 | * 19 | * It is important to note that event flags are simply hints about the 20 | * sort of operations that occurred at that path. 21 | * 22 | * Furthermore, the FSEvent stream should NOT be treated as a form of 23 | * historical log that could somehow be replayed to arrive at the 24 | * current state of the file system. 25 | * 26 | * The FSEvent stream simply indicates what paths changed; and clients 27 | * need to reconcile what is really in the file system with their internal 28 | * data model - and recognize that what is actually in the file system can 29 | * change immediately after you check it. 30 | */ 31 | public struct EonilFSEventsEventFlags: OptionSet { 32 | public let rawValue: FSEventStreamEventFlags 33 | public init(rawValue: FSEventStreamEventFlags) { 34 | self.rawValue = rawValue 35 | } 36 | fileprivate init(rawValue: Int) { 37 | self.rawValue = FSEventStreamEventFlags(truncatingIfNeeded: rawValue) 38 | } 39 | } 40 | 41 | public extension EonilFSEventsEventFlags { 42 | 43 | /* 44 | * There was some change in the directory at the specific path 45 | * supplied in this event. 46 | */ 47 | static var none: EonilFSEventsEventFlags { 48 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagNone) 49 | } 50 | 51 | /* 52 | * Your application must rescan not just the directory given in the 53 | * event, but all its children, recursively. This can happen if there 54 | * was a problem whereby events were coalesced hierarchically. For 55 | * example, an event in /Users/jsmith/Music and an event in 56 | * /Users/jsmith/Pictures might be coalesced into an event with this 57 | * flag set and path=/Users/jsmith. If this flag is set you may be 58 | * able to get an idea of whether the bottleneck happened in the 59 | * kernel (less likely) or in your client (more likely) by checking 60 | * for the presence of the informational flags 61 | * kFSEventStreamEventFlagUserDropped or 62 | * kFSEventStreamEventFlagKernelDropped. 63 | */ 64 | static var mustScanSubDirs: EonilFSEventsEventFlags { 65 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagMustScanSubDirs) 66 | } 67 | 68 | /* 69 | * The kFSEventStreamEventFlagUserDropped or 70 | * kFSEventStreamEventFlagKernelDropped flags may be set in addition 71 | * to the kFSEventStreamEventFlagMustScanSubDirs flag to indicate 72 | * that a problem occurred in buffering the events (the particular 73 | * flag set indicates where the problem occurred) and that the client 74 | * must do a full scan of any directories (and their subdirectories, 75 | * recursively) being monitored by this stream. If you asked to 76 | * monitor multiple paths with this stream then you will be notified 77 | * about all of them. Your code need only check for the 78 | * kFSEventStreamEventFlagMustScanSubDirs flag; these flags (if 79 | * present) only provide information to help you diagnose the problem. 80 | */ 81 | static var userDropped: EonilFSEventsEventFlags { 82 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagUserDropped) 83 | } 84 | 85 | /* 86 | * The kFSEventStreamEventFlagUserDropped or 87 | * kFSEventStreamEventFlagKernelDropped flags may be set in addition 88 | * to the kFSEventStreamEventFlagMustScanSubDirs flag to indicate 89 | * that a problem occurred in buffering the events (the particular 90 | * flag set indicates where the problem occurred) and that the client 91 | * must do a full scan of any directories (and their subdirectories, 92 | * recursively) being monitored by this stream. If you asked to 93 | * monitor multiple paths with this stream then you will be notified 94 | * about all of them. Your code need only check for the 95 | * kFSEventStreamEventFlagMustScanSubDirs flag; these flags (if 96 | * present) only provide information to help you diagnose the problem. 97 | */ 98 | static var kernelDropped: EonilFSEventsEventFlags { 99 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagKernelDropped) 100 | } 101 | 102 | /* 103 | * If kFSEventStreamEventFlagEventIdsWrapped is set, it means the 104 | * 64-bit event ID counter wrapped around. As a result, 105 | * previously-issued event ID's are no longer valid arguments for the 106 | * sinceWhen parameter of the FSEventStreamCreate...() functions. 107 | */ 108 | static var idsWrapped: EonilFSEventsEventFlags { 109 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagEventIdsWrapped) 110 | } 111 | 112 | /* 113 | * Denotes a sentinel event sent to mark the end of the "historical" 114 | * events sent as a result of specifying a sinceWhen value in the 115 | * FSEventStreamCreate...() call that created this event stream. (It 116 | * will not be sent if kFSEventStreamEventIdSinceNow was passed for 117 | * sinceWhen.) After invoking the client's callback with all the 118 | * "historical" events that occurred before now, the client's 119 | * callback will be invoked with an event where the 120 | * kFSEventStreamEventFlagHistoryDone flag is set. The client should 121 | * ignore the path supplied in this callback. 122 | */ 123 | static var historyDone: EonilFSEventsEventFlags { 124 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagHistoryDone) 125 | } 126 | 127 | /* 128 | * Denotes a special event sent when there is a change to one of the 129 | * directories along the path to one of the directories you asked to 130 | * watch. When this flag is set, the event ID is zero and the path 131 | * corresponds to one of the paths you asked to watch (specifically, 132 | * the one that changed). The path may no longer exist because it or 133 | * one of its parents was deleted or renamed. Events with this flag 134 | * set will only be sent if you passed the flag 135 | * kFSEventStreamCreateFlagWatchRoot to FSEventStreamCreate...() when 136 | * you created the stream. 137 | */ 138 | static var rootChanged: EonilFSEventsEventFlags { 139 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagRootChanged) 140 | } 141 | 142 | /* 143 | * Denotes a special event sent when a volume is mounted underneath 144 | * one of the paths being monitored. The path in the event is the 145 | * path to the newly-mounted volume. You will receive one of these 146 | * notifications for every volume mount event inside the kernel 147 | * (independent of DiskArbitration). Beware that a newly-mounted 148 | * volume could contain an arbitrarily large directory hierarchy. 149 | * Avoid pitfalls like triggering a recursive scan of a non-local 150 | * filesystem, which you can detect by checking for the absence of 151 | * the MNT_LOCAL flag in the f_flags returned by statfs(). Also be 152 | * aware of the MNT_DONTBROWSE flag that is set for volumes which 153 | * should not be displayed by user interface elements. 154 | */ 155 | static var mount: EonilFSEventsEventFlags { 156 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagMount) 157 | } 158 | 159 | /* 160 | * Denotes a special event sent when a volume is unmounted underneath 161 | * one of the paths being monitored. The path in the event is the 162 | * path to the directory from which the volume was unmounted. You 163 | * will receive one of these notifications for every volume unmount 164 | * event inside the kernel. This is not a substitute for the 165 | * notifications provided by the DiskArbitration framework; you only 166 | * get notified after the unmount has occurred. Beware that 167 | * unmounting a volume could uncover an arbitrarily large directory 168 | * hierarchy, although Mac OS X never does that. 169 | */ 170 | static var unmount: EonilFSEventsEventFlags { 171 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagUnmount) 172 | } 173 | 174 | /* 175 | * A file system object was created at the specific path supplied in this event. 176 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.) 177 | */ 178 | @available(OSX 10.7, *) 179 | static var itemCreated: EonilFSEventsEventFlags { 180 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemCreated) 181 | } 182 | 183 | /* 184 | * A file system object was removed at the specific path supplied in this event. 185 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.) 186 | */ 187 | @available(OSX 10.7, *) 188 | static var itemRemoved: EonilFSEventsEventFlags { 189 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemRemoved) 190 | } 191 | 192 | /* 193 | * A file system object at the specific path supplied in this event had its metadata modified. 194 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.) 195 | */ 196 | @available(OSX 10.7, *) 197 | static var itemInodeMetaMod: EonilFSEventsEventFlags { 198 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemInodeMetaMod) 199 | } 200 | 201 | /* 202 | * A file system object was renamed at the specific path supplied in this event. 203 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.) 204 | */ 205 | @available(OSX 10.7, *) 206 | static var itemRenamed: EonilFSEventsEventFlags { 207 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemRenamed) 208 | } 209 | 210 | /* 211 | * A file system object at the specific path supplied in this event had its data modified. 212 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.) 213 | */ 214 | @available(OSX 10.7, *) 215 | static var itemModified: EonilFSEventsEventFlags { 216 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemModified) 217 | } 218 | 219 | /* 220 | * A file system object at the specific path supplied in this event had its FinderInfo data modified. 221 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.) 222 | */ 223 | @available(OSX 10.7, *) 224 | static var itemFinderInfoMod: EonilFSEventsEventFlags { 225 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemFinderInfoMod) 226 | } 227 | 228 | /* 229 | * A file system object at the specific path supplied in this event had its ownership changed. 230 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.) 231 | */ 232 | @available(OSX 10.7, *) 233 | static var itemChangeOwner: EonilFSEventsEventFlags { 234 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemChangeOwner) 235 | } 236 | 237 | /* 238 | * A file system object at the specific path supplied in this event had its extended attributes modified. 239 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.) 240 | */ 241 | @available(OSX 10.7, *) 242 | static var itemXattrMod: EonilFSEventsEventFlags { 243 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemXattrMod) 244 | } 245 | 246 | /* 247 | * The file system object at the specific path supplied in this event is a regular file. 248 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.) 249 | */ 250 | @available(OSX 10.7, *) 251 | static var itemIsFile: EonilFSEventsEventFlags { 252 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemIsFile) 253 | } 254 | 255 | /* 256 | * The file system object at the specific path supplied in this event is a directory. 257 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.) 258 | */ 259 | @available(OSX 10.7, *) 260 | static var itemIsDir: EonilFSEventsEventFlags { 261 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemIsDir) 262 | } 263 | 264 | /* 265 | * The file system object at the specific path supplied in this event is a symbolic link. 266 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.) 267 | */ 268 | @available(OSX 10.7, *) 269 | static var itemIsSymlink: EonilFSEventsEventFlags { 270 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemIsSymlink) 271 | } 272 | 273 | /* 274 | * Indicates the event was triggered by the current process. 275 | * (This flag is only ever set if you specified the MarkSelf flag when creating the stream.) 276 | */ 277 | @available(OSX 10.9, *) 278 | static var ownEvent: EonilFSEventsEventFlags { 279 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagOwnEvent) 280 | } 281 | 282 | /* 283 | * Indicates the object at the specified path supplied in this event is a hard link. 284 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.) 285 | */ 286 | @available(OSX 10.10, *) 287 | static var itemIsHardlink: EonilFSEventsEventFlags { 288 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemIsHardlink) 289 | } 290 | 291 | /* Indicates the object at the specific path supplied in this event was the last hard link. 292 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.) 293 | */ 294 | @available(OSX 10.10, *) 295 | static var itemIsLastHardlink: EonilFSEventsEventFlags { 296 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemIsLastHardlink) 297 | } 298 | 299 | } 300 | 301 | extension EonilFSEventsEventFlags: Hashable { 302 | public var hashValue: Int { 303 | return rawValue.hashValue 304 | } 305 | } 306 | extension EonilFSEventsEventFlags: CustomStringConvertible, CustomDebugStringConvertible { 307 | // private static func getAllFlags() -> [EonilFSEventsEventFlags] { 308 | // return [ 309 | //// .none, 310 | // .mustScanSubDirs, 311 | // .userDropped, 312 | // .kernelDropped, 313 | // .idsWrapped, 314 | // .historyDone, 315 | // .rootChanged, 316 | // .mount, 317 | // .unmount, 318 | // .itemCreated, 319 | // .itemRemoved, 320 | // .itemInodeMetaMod, 321 | // .itemRenamed, 322 | // .itemModified, 323 | // .itemFinderInfoMod, 324 | // .itemChangeOwner, 325 | // .itemXattrMod, 326 | // .itemIsFile, 327 | // .itemIsDir, 328 | // .itemIsSymlink, 329 | // .ownEvent, 330 | // .itemIsHardlink, 331 | // .itemIsLastHardlink, 332 | // ] 333 | // } 334 | private static func getNameMapping() -> [EonilFSEventsEventFlags: String] { 335 | return [ 336 | // .none: ".none", 337 | .mustScanSubDirs: ".mustScanSubDirs", 338 | .userDropped: ".userDropped", 339 | .kernelDropped: ".kernelDropped", 340 | .idsWrapped: ".idsWrapped", 341 | .historyDone: ".historyDone", 342 | .rootChanged: ".rootChanged", 343 | .mount: ".mount", 344 | .unmount: ".unmount", 345 | .itemCreated: ".itemCreated", 346 | .itemRemoved: ".itemRemoved", 347 | .itemInodeMetaMod: ".itemInodeMetaMod", 348 | .itemRenamed: ".itemRenamed", 349 | .itemModified: ".itemModified", 350 | .itemFinderInfoMod: ".itemFinderInfoMod", 351 | .itemChangeOwner: ".itemChangeOwner", 352 | .itemXattrMod: ".itemXattrMod", 353 | .itemIsFile: ".itemIsFile", 354 | .itemIsDir: ".itemIsDir", 355 | .itemIsSymlink: ".itemIsSymlink", 356 | .ownEvent: ".ownEvent", 357 | .itemIsHardlink: ".itemIsHardlink", 358 | .itemIsLastHardlink: ".itemIsLastHardlink", 359 | ] 360 | } 361 | public var description: String { 362 | return debugDescription 363 | } 364 | public var debugDescription: String { 365 | let ns = EonilFSEventsEventFlags.getNameMapping() 366 | let ns1 = ns.filter({ contains($0.key) }).map({ $0.value }) 367 | return "[\(ns1.joined(separator: ","))]" 368 | } 369 | } 370 | -------------------------------------------------------------------------------- /Sources/EonilFSEvents/EonilFSEventStreamEventID.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EonilFSEventsEventID.swift 3 | // EonilFSEvents 4 | // 5 | // Created by Hoon H. on 2016/10/02. 6 | // 7 | // 8 | 9 | import Foundation 10 | import CoreServices 11 | 12 | public struct EonilFSEventsEventID: Hashable, RawRepresentable { 13 | public let rawValue: FSEventStreamEventId 14 | public init(rawValue: FSEventStreamEventId) { 15 | self.rawValue = rawValue 16 | } 17 | fileprivate init(rawValue: UInt) { 18 | self.rawValue = FSEventStreamEventId(UInt32(truncatingIfNeeded: rawValue)) 19 | } 20 | } 21 | public func == (a: EonilFSEventsEventID, b: EonilFSEventsEventID) -> Bool { 22 | return a.rawValue == b.rawValue 23 | } 24 | 25 | public extension EonilFSEventsEventID { 26 | static var now: EonilFSEventsEventID { 27 | return EonilFSEventsEventID(rawValue: kFSEventStreamEventIdSinceNow) 28 | } 29 | /* 30 | * FSEventsGetCurrentEventId() 31 | * 32 | * Discussion: 33 | * Fetches the most recently generated event ID, system-wide (not 34 | * just for one stream). By thetime it is returned to your 35 | * application even newer events may have already been generated. 36 | * 37 | * Result: 38 | * The event ID of the most recent event generated by the system. 39 | * 40 | * Availability: 41 | * Mac OS X: in version 10.5 and later in CoreServices.framework 42 | * CarbonLib: not available 43 | * Non-Carbon CFM: not available 44 | */ 45 | @available(macOS, introduced: 10.5) 46 | @available(iOS, introduced: 6.0) 47 | static func getCurrentEventId() -> EonilFSEventsEventID { 48 | let eventId = FSEventsGetCurrentEventId() 49 | return EonilFSEventsEventID(rawValue: eventId) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Sources/EonilFSEvents/EonilFSEventStreamIllogicalErrorLog.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EonilFSEventsIllogicalErrorLog.swift 3 | // EonilFSEvents 4 | // 5 | // Created by Hoon H. on 2016/10/02. 6 | // 7 | // 8 | 9 | /// An error that is very unlikely to happen if this library code is properly written. 10 | /// 11 | public struct EonilFSEventsIllogicalErrorLog { 12 | public var code: EonilFSEventsCriticalErrorCode 13 | public var message: String? 14 | init(code: EonilFSEventsCriticalErrorCode) { 15 | self.code = code 16 | } 17 | init(code: EonilFSEventsCriticalErrorCode, message: String) { 18 | self.code = code 19 | self.message = message 20 | } 21 | func cast() { 22 | EonilFSEventsIllogicalErrorLog.handler(self) 23 | } 24 | 25 | /// Can be called at any thread. 26 | public static var handler: (EonilFSEventsIllogicalErrorLog) -> () = { assert(false, "EonilFSEvents: \($0)") } 27 | } 28 | 29 | public enum EonilFSEventsCriticalErrorCode { 30 | case missingContextRawPointerValue 31 | case unexpectedPathValueType 32 | case unmatchedEventParameterCounts 33 | } 34 | -------------------------------------------------------------------------------- /Sources/EonilFSEvents/EonilFSEvents.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EonilFSEvents.swift 3 | // EonilFSEvents 4 | // 5 | // Created by Hoon H. on 2016/10/02. 6 | // 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | /// 13 | /// Simple access to file-system events. 14 | /// 15 | /// - Note: 16 | /// This is specifically designed for GUI apps. 17 | /// Use only in main thread. 18 | /// If you want to access all the options of "FSEvents", 19 | /// use `EonilFSEvents` class directly. 20 | /// 21 | public struct EonilFSEvents { 22 | public static func startWatching(paths: [String], for id: ObjectIdentifier, with handler: @escaping (EonilFSEventsEvent) -> ()) throws { 23 | assert(Thread.isMainThread) 24 | assert(watchers[id] == nil) 25 | // This is convenient wrapper for UI. 26 | // UI usually needs quicker response rather than maximum throughput. 27 | // Tuned for quickest response. 28 | // For non-UI code, I strongly recommend to instantiate `EonilFSEvents` yourself 29 | // with proper parameters. 30 | let s = try EonilFSEventStream( 31 | pathsToWatch: paths, 32 | sinceWhen: .now, 33 | latency: 0, 34 | flags: [.noDefer, .fileEvents], 35 | handler: handler) 36 | s.setDispatchQueue(DispatchQueue.main) 37 | try s.start() 38 | watchers[id] = s 39 | } 40 | public static func stopWatching(for id: ObjectIdentifier) { 41 | assert(Thread.isMainThread) 42 | 43 | guard let s = watchers[id] else { return } 44 | s.stop() 45 | s.invalidate() 46 | watchers[id] = nil 47 | } 48 | } 49 | private var watchers = [ObjectIdentifier: EonilFSEventStream]() 50 | -------------------------------------------------------------------------------- /Sources/EonilFSEventsDemoCLI/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // EonilFSEventsDemoCLI 4 | // 5 | // Created by Henry on 2018/12/27. 6 | // 7 | 8 | import Foundation 9 | import EonilFSEvents 10 | 11 | let k = NSObject() 12 | try EonilFSEvents.startWatching( 13 | paths: [NSHomeDirectory()], 14 | for: ObjectIdentifier(k), 15 | with: { e in print(e) }) 16 | 17 | RunLoop.main.run() 18 | -------------------------------------------------------------------------------- /test.zsh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zsh 2 | 3 | rm -rf .build build 4 | 5 | swift build 6 | # I don't know why, but "xcodebuild" doesn't work 7 | # without explicit setting of "SYMROOT". 8 | # It seems Xcode have some issues. 9 | OPTS=SYMROOT=`pwd`/build 10 | 11 | DEMO=EonilFSEventsDemoGUI 12 | cd $DEMO 13 | xcodebuild -project $DEMO.xcodeproj -target $DEMO -configuration Debug $OPTS 14 | xcodebuild -project $DEMO.xcodeproj -target $DEMO -configuration Release $OPTS 15 | cd .. 16 | 17 | # I can't figure out how to build without provisioning profile for Mac Catalyst. 18 | # Therefore, test has been disabled. You can perform test manually by opening the project. 19 | #cd BuildTest 20 | #xcodebuild -project BuildTest.xcodeproj -target MacOSBuildTest -configuration Debug $OPTS 21 | #xcodebuild -project BuildTest.xcodeproj -target MacOSBuildTest -configuration Release $OPTS 22 | #xcodebuild -project BuildTest.xcodeproj -target MacCatalystBuildTest -configuration Debug $OPTS 23 | #xcodebuild -project BuildTest.xcodeproj -target MacCatalystBuildTest -configuration Release $OPTS 24 | #cd .. 25 | --------------------------------------------------------------------------------