Permalink
Browse files

Added DTFolderMonitor and integrated in DTZipArchive Demo

  • Loading branch information...
1 parent a3bcb18 commit 43e991314c60f63ddd3804c4fd13b1db53c28807 @odrobnik odrobnik committed Aug 5, 2013
@@ -0,0 +1,48 @@
+//
+// DTFolderMonitor.h
+// DTFoundation
+//
+// Created by Oliver Drobnik on 05.08.13.
+// Copyright (c) 2013 Cocoanetics. All rights reserved.
+//
+
+// The block to execute if a monitored folder changes
+typedef void (^DTFolderMonitorBlock) (void);
+
+/**
+ Class for monitoring changes on a folder. This can be used to monitor the application documents folder for changes in the files there if the user adds or removes files via iTunes file sharing.
+ */
+
+@interface DTFolderMonitor : NSObject
+
+/**
+ @name Creating a Folder Monitor
+ */
+
+/**
+ Creates a new DTFolderMonitor to watch the folder at the given URL. Whenever there is a change on this folder the block is executed.
+
+ The URL must be a file URL. Both the URL and the block parameter are mandatory. The block is being dispatched on a background queue.
+
+ @param URL The monitored folder URL
+ @param block The block to execute if the folder is being modified
+ @returns The instantiated monitor in suspended mode. Call -startMonitoring to start monitoring.
+ */
++ (DTFolderMonitor *)folderMonitorForURL:(NSURL *)URL block:(DTFolderMonitorBlock)block;
+
+
+/**
+ @name Starting/Stopping Monitoring
+ */
+
+/**
+ Start monitoring the folder. A monitor can be started and stopped multiple times.
+ */
+- (void)startMonitoring;
+
+/**
+ Stop monitoring the folder. A monitor can be started and stopped multiple times.
+ */
+- (void)stopMonitoring;
+
+@end
@@ -0,0 +1,106 @@
+//
+// DTFolderMonitor.m
+// DTFoundation
+//
+// Created by Oliver Drobnik on 05.08.13.
+// Copyright (c) 2013 Cocoanetics. All rights reserved.
+//
+
+#import "DTFolderMonitor.h"
+
+@implementation DTFolderMonitor
+{
+ NSURL *_URL;
+ DTFolderMonitorBlock _block;
+
+ int _fileDescriptor;
+ dispatch_queue_t _queue;
+ dispatch_source_t _source;
+}
+
++ (DTFolderMonitor *)folderMonitorForURL:(NSURL *)URL block:(DTFolderMonitorBlock)block
+{
+ return [[DTFolderMonitor alloc] initWithURL:URL block:block];
+}
+
+- (instancetype)initWithURL:(NSURL *)URL block:(DTFolderMonitorBlock)block
+{
+ NSParameterAssert(URL);
+ NSParameterAssert(block);
+ NSAssert([URL isFileURL], @"URL Parameter must be a folder URL");
+
+ self = [super init];
+
+ if (self)
+ {
+ _URL = URL;
+ _block = [block copy];
+
+ NSString *path = [_URL path];
+ _fileDescriptor = open([path fileSystemRepresentation], O_EVTONLY);
+
+ if (!_fileDescriptor)
+ {
+ return nil;
+ }
+
+ _queue = dispatch_queue_create("DTFolderMonitor Queue", 0);
+ }
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [self stopMonitoring];
+
+#if OS_OBJECT_USE_OBJC
+ dispatch_release(_queue);
+#endif
+}
+
+- (void)startMonitoring
+{
+ @synchronized(self)
+ {
+ if (_source)
+ {
+ return;
+ }
+
+ // watch the file descriptor for writes
+ _source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, _fileDescriptor, DISPATCH_VNODE_WRITE, _queue);
+
+ // call the passed block if the source is modified
+ dispatch_source_set_event_handler(_source, _block);
+
+ // close the file descriptor when the dispatch source is cancelled
+ dispatch_source_set_cancel_handler(_source, ^{
+
+ close(_fileDescriptor);
+ });
+
+ // at this point the dispatch source is paused, so start watching
+ dispatch_resume(_source);
+ }
+}
+
+- (void)stopMonitoring
+{
+ @synchronized(self)
+ {
+ if (!_source)
+ {
+ return;
+ }
+
+ dispatch_source_cancel(_source);
+
+#if !OS_OBJECT_USE_OBJC
+ dispatch_release(_source);
+#endif
+ _source = nil;
+ }
+}
+
+@end
@@ -184,6 +184,12 @@
A77DD42614E825FC00F34B03 /* zip.h in Headers */ = {isa = PBXBuildFile; fileRef = A77DD41514E825FC00F34B03 /* zip.h */; settings = {ATTRIBUTES = (Public, ); }; };
A77DD42714E825FC00F34B03 /* zip.h in Headers */ = {isa = PBXBuildFile; fileRef = A77DD41514E825FC00F34B03 /* zip.h */; };
A78220BB168060CA005B602D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7F4DFFA147FD08F00F4059A /* Foundation.framework */; };
+ A78D661D17AFFCCC0039F5E6 /* DTFolderMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = A78D661B17AFFCCC0039F5E6 /* DTFolderMonitor.h */; };
+ A78D661E17AFFCCC0039F5E6 /* DTFolderMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = A78D661B17AFFCCC0039F5E6 /* DTFolderMonitor.h */; };
+ A78D661F17AFFCCC0039F5E6 /* DTFolderMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = A78D661B17AFFCCC0039F5E6 /* DTFolderMonitor.h */; };
+ A78D662017AFFCCC0039F5E6 /* DTFolderMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = A78D661C17AFFCCC0039F5E6 /* DTFolderMonitor.m */; };
+ A78D662117AFFCCC0039F5E6 /* DTFolderMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = A78D661C17AFFCCC0039F5E6 /* DTFolderMonitor.m */; };
+ A78D662217AFFCCC0039F5E6 /* DTFolderMonitor.m in Sources */ = {isa = PBXBuildFile; fileRef = A78D661C17AFFCCC0039F5E6 /* DTFolderMonitor.m */; };
A79231CE157A0B9400C3ACBB /* NSURL+DTUnshorten.h in Headers */ = {isa = PBXBuildFile; fileRef = A79231CC157A0B9400C3ACBB /* NSURL+DTUnshorten.h */; settings = {ATTRIBUTES = (Public, ); }; };
A79231CF157A0B9400C3ACBB /* NSURL+DTUnshorten.h in Headers */ = {isa = PBXBuildFile; fileRef = A79231CC157A0B9400C3ACBB /* NSURL+DTUnshorten.h */; };
A79231D0157A0B9400C3ACBB /* NSURL+DTUnshorten.m in Sources */ = {isa = PBXBuildFile; fileRef = A79231CD157A0B9400C3ACBB /* NSURL+DTUnshorten.m */; };
@@ -602,6 +608,8 @@
A77DD41514E825FC00F34B03 /* zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zip.h; sourceTree = "<group>"; };
A78220BA168060CA005B602D /* libDTUTI_iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDTUTI_iOS.a; sourceTree = BUILT_PRODUCTS_DIR; };
A7859D3D16DF8D180076F2DB /* AppledocSettings.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AppledocSettings.plist; sourceTree = "<group>"; };
+ A78D661B17AFFCCC0039F5E6 /* DTFolderMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTFolderMonitor.h; sourceTree = "<group>"; };
+ A78D661C17AFFCCC0039F5E6 /* DTFolderMonitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTFolderMonitor.m; sourceTree = "<group>"; };
A78EDD1717A65AD700480205 /* DTScriptExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DTScriptExpression.h; sourceTree = "<group>"; };
A78EDD1817A65AD700480205 /* DTScriptExpression.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DTScriptExpression.m; sourceTree = "<group>"; };
A78EDD1917A65AD700480205 /* DTScriptVariable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DTScriptVariable.h; sourceTree = "<group>"; };
@@ -1346,6 +1354,8 @@
A77D5BF916E4961A00A45C28 /* DTBase64Coding.m */,
A7D6F2E315063448001CACDD /* DTExtendedFileAttributes.h */,
A7D6F2E415063448001CACDD /* DTExtendedFileAttributes.m */,
+ A78D661B17AFFCCC0039F5E6 /* DTFolderMonitor.h */,
+ A78D661C17AFFCCC0039F5E6 /* DTFolderMonitor.m */,
A70B4CC71486621B00873A4A /* DTVersion.h */,
A70B4CC81486621B00873A4A /* DTVersion.m */,
A7FB1218175C9D5000D4B7F0 /* DTWeakSupport.h */,
@@ -1584,6 +1594,7 @@
A7C92B6A174F9AEC0019D70A /* UIViewController+DTSidePanelController.h in Headers */,
A7FB1216175C9C8B00D4B7F0 /* DTSidePanelController.h in Headers */,
A7FB121A175C9D5000D4B7F0 /* DTWeakSupport.h in Headers */,
+ A78D661E17AFFCCC0039F5E6 /* DTFolderMonitor.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1606,6 +1617,7 @@
A77D5BFC16E4961A00A45C28 /* DTBase64Coding.h in Headers */,
A7FB121B175C9D5000D4B7F0 /* DTWeakSupport.h in Headers */,
A70C4FFB17AA7F7D00000DF5 /* DTUtils.h in Headers */,
+ A78D661F17AFFCCC0039F5E6 /* DTFolderMonitor.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1664,6 +1676,7 @@
A70C4FFE17AA7F9C00000DF5 /* DTActionSheet.h in Headers */,
A70C4FFF17AA7F9C00000DF5 /* DTAlertView.h in Headers */,
A70C500017AA7F9C00000DF5 /* UIView+DTActionHandlers.h in Headers */,
+ A78D661D17AFFCCC0039F5E6 /* DTFolderMonitor.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2238,6 +2251,7 @@
A70C4FEA17AA7F0200000DF5 /* NSScanner+DTScripting.m in Sources */,
A70C4FF117AA7F2000000DF5 /* DTObjectBlockExecutor.m in Sources */,
A70C4FF217AA7F2000000DF5 /* NSObject+DTRuntime.m in Sources */,
+ A78D662117AFFCCC0039F5E6 /* DTFolderMonitor.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2282,6 +2296,7 @@
A70C4FF017AA7F0700000DF5 /* NSScanner+DTScripting.m in Sources */,
A70C4FF517AA7F2300000DF5 /* DTObjectBlockExecutor.m in Sources */,
A70C4FF617AA7F2300000DF5 /* NSObject+DTRuntime.m in Sources */,
+ A78D662217AFFCCC0039F5E6 /* DTFolderMonitor.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2359,6 +2374,7 @@
A70C4FED17AA7F0300000DF5 /* NSScanner+DTScripting.m in Sources */,
A70C4FF317AA7F2100000DF5 /* DTObjectBlockExecutor.m in Sources */,
A70C4FF417AA7F2100000DF5 /* NSObject+DTRuntime.m in Sources */,
+ A78D662017AFFCCC0039F5E6 /* DTFolderMonitor.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3328,17 +3344,15 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_WARN_EMPTY_BODY = YES;
- CODE_SIGN_IDENTITY = "iPhone Developer: Stefan Gugarel (5V5NEAJJ6M)";
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Stefan Gugarel (5V5NEAJJ6M)";
+ CODE_SIGN_IDENTITY = "iPhone Developer";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Demo/DTZipArchiveDemo/DTZipArchiveDemo-Prefix.pch";
INFOPLIST_FILE = "Demo/DTZipArchiveDemo/DTZipArchiveDemo-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 6.1;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = DTZipArchive;
- PROVISIONING_PROFILE = "EE8FE43F-35E0-4192-91C6-0BFF3878BF03";
- "PROVISIONING_PROFILE[sdk=iphoneos*]" = "EE8FE43F-35E0-4192-91C6-0BFF3878BF03";
+ PROVISIONING_PROFILE = "";
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
};
@@ -3350,7 +3364,6 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_WARN_EMPTY_BODY = YES;
- CODE_SIGN_IDENTITY = "iPhone Developer: Stefan Gugarel (5V5NEAJJ6M)";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Demo/DTZipArchiveDemo/DTZipArchiveDemo-Prefix.pch";
@@ -3359,7 +3372,6 @@
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = DTZipArchive;
- PROVISIONING_PROFILE = "EE8FE43F-35E0-4192-91C6-0BFF3878BF03";
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
};
@@ -3555,6 +3567,7 @@
FAF37A3717AFDD93009AC27C /* Release */,
);
defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
@@ -33,6 +33,14 @@ @implementation ViewController
ZipArchiveManager *_zipArchiveManager;
}
+- (void)_prepIcons
+{
+ for (ZipArchiveModel *zipArchiveModel in _zipArchiveManager.archives)
+ {
+ [self _setupDocumentControllerWithURL:zipArchiveModel.URL];
+ }
+}
+
- (void)viewDidLoad
{
[super viewDidLoad];
@@ -42,10 +50,15 @@ - (void)viewDidLoad
NSURL *documentsURL = [NSURL fileURLWithPath:documentsPath];
_zipArchiveManager = [[ZipArchiveManager alloc] initWithURL:documentsURL];
- for (ZipArchiveModel *zipArchiveModel in _zipArchiveManager.archives)
- {
- [self _setupDocumentControllerWithURL:zipArchiveModel.URL];
- }
+ // monitor for changes to the list of archives, e.g. iTunes file sharing
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(archivesDidChange:) name:ZipArchiveManagerDidReloadArchivesNotification object:_zipArchiveManager];
+
+ [self _prepIcons];
+}
+
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)_setupDocumentControllerWithURL:(NSURL *)url
@@ -150,4 +163,14 @@ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
}
}
+#pragma mark - Notifications
+- (void)archivesDidChange:(NSNotification *)notification
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+
+ [self _prepIcons];
+ [self.tableView reloadData];
+ });
+}
+
@end
@@ -8,6 +8,9 @@
#import <Foundation/Foundation.h>
+// notification that gets sent if the zip archives at the location get reloaded
+extern NSString * const ZipArchiveManagerDidReloadArchivesNotification;
+
@class ZipArchiveModel;
@interface ZipArchiveManager : NSObject
@@ -10,10 +10,16 @@
#import "ZipArchiveModel.h"
#import "DTZipArchive.h"
#import "NSString+DTPaths.h"
+#import "DTFolderMonitor.h"
+
+
+NSString * const ZipArchiveManagerDidReloadArchivesNotification = @"ZipArchiveManagerDidReloadArchivesNotification";
@implementation ZipArchiveManager
{
NSMutableDictionary *_zipArchivesDictionary;
+
+ DTFolderMonitor *_documentsFolderMonitor;
}
@@ -25,6 +31,17 @@ - (id)initWithURL:(NSURL *)URL
_URL = URL;
[self _setup];
+
+ // install a folder monitor
+ __weak ZipArchiveManager *weakself = self;
+ _documentsFolderMonitor = [DTFolderMonitor folderMonitorForURL:_URL block:^{
+
+ [weakself _setup];
+
+ [[NSNotificationCenter defaultCenter] postNotificationName:ZipArchiveManagerDidReloadArchivesNotification object:weakself];
+ }];
+
+ [_documentsFolderMonitor startMonitoring];
}
return self;
}

0 comments on commit 43e9913

Please sign in to comment.