mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-14 17:32:17 +00:00
More improvements on modelchangeobserving
This commit is contained in:
@@ -53,6 +53,7 @@ NSString *const MPEntryTableURLColumnIdentifier = @"MPEntryTableURLColumnIdentif
|
||||
NSString *const MPEntryTableNotesColumnIdentifier = @"MPEntryTableNotesColumnIdentifier";
|
||||
NSString *const MPEntryTableAttachmentColumnIdentifier = @"MPEntryTableAttachmentColumnIdentifier";
|
||||
NSString *const MPEntryTableModfiedColumnIdentifier = @"MPEntryTableModfiedColumnIdentifier";
|
||||
NSString *const MPEntryTableHistoryColumnIdentifier = @"MPEntryTableHistoryColumnIdentifier";
|
||||
|
||||
NSString *const _MPTableImageCellView = @"ImageCell";
|
||||
NSString *const _MPTableStringCellView = @"StringCell";
|
||||
@@ -128,12 +129,15 @@ NSString *const _MPTableSecurCellView = @"PasswordCell";
|
||||
NSTableColumn *attachmentsColumn = [[NSTableColumn alloc] initWithIdentifier:MPEntryTableAttachmentColumnIdentifier];
|
||||
NSTableColumn *notesColumn = [[NSTableColumn alloc] initWithIdentifier:MPEntryTableNotesColumnIdentifier];
|
||||
NSTableColumn *modifiedColumn = [[NSTableColumn alloc] initWithIdentifier:MPEntryTableModfiedColumnIdentifier];
|
||||
NSTableColumn *historyColumn = [[NSTableColumn alloc] initWithIdentifier:MPEntryTableHistoryColumnIdentifier];
|
||||
notesColumn.minWidth = 40.0;
|
||||
attachmentsColumn.minWidth = 40.0;
|
||||
modifiedColumn.minWidth = 40.0;
|
||||
historyColumn.minWidth = 40.0;
|
||||
[self.entryTable addTableColumn:notesColumn];
|
||||
[self.entryTable addTableColumn:attachmentsColumn];
|
||||
[self.entryTable addTableColumn:modifiedColumn];
|
||||
[self.entryTable addTableColumn:historyColumn];
|
||||
|
||||
parentColumn.identifier = MPEntryTableParentColumnIdentifier;
|
||||
titleColumn.identifier = MPEntryTableTitleColumnIdentifier;
|
||||
@@ -161,6 +165,7 @@ NSString *const _MPTableSecurCellView = @"PasswordCell";
|
||||
notesColumn.headerCell.stringValue = NSLocalizedString(@"NOTES", "");
|
||||
attachmentsColumn.headerCell.stringValue = NSLocalizedString(@"ATTACHMENTS", "");
|
||||
modifiedColumn.headerCell.stringValue = NSLocalizedString(@"MODIFIED", "");
|
||||
historyColumn.headerCell.stringValue = NSLocalizedString(@"HISTORY", "");
|
||||
|
||||
[self.entryTable bind:NSContentBinding toObject:self.entryArrayController withKeyPath:NSStringFromSelector(@selector(arrangedObjects)) options:nil];
|
||||
[self.entryTable bind:NSSortDescriptorsBinding toObject:self.entryArrayController withKeyPath:NSStringFromSelector(@selector(sortDescriptors)) options:nil];
|
||||
@@ -235,6 +240,7 @@ NSString *const _MPTableSecurCellView = @"PasswordCell";
|
||||
BOOL isAttachmentColumn = [tableColumn.identifier isEqualToString:MPEntryTableAttachmentColumnIdentifier];
|
||||
BOOL isNotesColumn = [tableColumn.identifier isEqualToString:MPEntryTableNotesColumnIdentifier];
|
||||
BOOL isModifedColumn = [tableColumn.identifier isEqualToString:MPEntryTableModfiedColumnIdentifier];
|
||||
BOOL isHistoryColumn = [tableColumn.identifier isEqualToString:MPEntryTableHistoryColumnIdentifier];
|
||||
|
||||
NSTableCellView *view = nil;
|
||||
if(isTitleColumn || isGroupColumn) {
|
||||
@@ -320,10 +326,16 @@ NSString *const _MPTableSecurCellView = @"PasswordCell";
|
||||
[view.textField bind:NSValueBinding toObject:view withKeyPath:notesKeyPath options:options];
|
||||
}
|
||||
else if(isAttachmentColumn) {
|
||||
NSString *binariesCoundKeyPath = [NSString stringWithFormat:@"%@.%@.@count",
|
||||
NSString *binariesCountKeyPath = [NSString stringWithFormat:@"%@.%@.@count",
|
||||
NSStringFromSelector(@selector(objectValue)),
|
||||
NSStringFromSelector(@selector(binaries))];
|
||||
[view.textField bind:NSValueBinding toObject:view withKeyPath:binariesCoundKeyPath options:nil];
|
||||
[view.textField bind:NSValueBinding toObject:view withKeyPath:binariesCountKeyPath options:nil];
|
||||
}
|
||||
else if(isHistoryColumn) {
|
||||
NSString *historyCountKeyPath = [NSString stringWithFormat:@"%@.%@.@count",
|
||||
NSStringFromSelector(@selector(objectValue)),
|
||||
NSStringFromSelector(@selector(history))];
|
||||
[view.textField bind:NSValueBinding toObject:view withKeyPath:historyCountKeyPath options:nil];
|
||||
}
|
||||
}
|
||||
return view;
|
||||
|
||||
@@ -23,15 +23,17 @@ FOUNDATION_EXTERN NSString *const MPDidChangeModelNotification;
|
||||
FOUNDATION_EXTERN NSString *const MPModelChangeObservingKeyPathKey;
|
||||
|
||||
@required
|
||||
- (void)observerModelChangesForKeyPath:(NSString *)keyPath;
|
||||
- (void)beginObservingModelChangesForKeyPath:(NSString *)keyPath;
|
||||
- (void)endObservingModelChangesForKeyPath:(NSString *)keyPath;
|
||||
@end
|
||||
|
||||
/* Use this helper to fire the right notifications */
|
||||
/* Use this helper to fire the right notifications. You can hold an instance to help in you implementation of setValue:forKeyPath and observerModelChangesForKeyPath: */
|
||||
@interface MPModelChangeObservingHelper : NSObject
|
||||
|
||||
+ (void)willChangeModelKeyPath:(NSString *)keyPath observer:(id<MPModelChangeObserving>)observer;
|
||||
+ (void)didChangeModelKeyPath:(NSString *)keyPath observer:(id<MPModelChangeObserving>)observer;
|
||||
|
||||
- (void)beginObservingModelChangesForKeyPath:(NSString *)keyPath;
|
||||
- (void)endObservingModelChangesForKeyPath:(NSString *)keyPath;
|
||||
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath forTarget:(id)target;
|
||||
|
||||
@end
|
||||
|
||||
@@ -13,6 +13,11 @@ NSString *const MPDidChangeModelNotification = @"com.hicknhack.macpass.MPDidChan
|
||||
|
||||
NSString *const MPModelChangeObservingKeyPathKey = @"MPModelChangeObservingKeyPathKey";
|
||||
|
||||
@interface MPModelChangeObservingHelper ()
|
||||
@property (strong) NSMutableSet<NSString *> *observedPaths;
|
||||
@property (strong) NSMutableSet<NSString *> *matchedPathsCache;
|
||||
@end
|
||||
|
||||
@implementation MPModelChangeObservingHelper
|
||||
|
||||
+ (void)willChangeModelKeyPath:(NSString *)keyPath observer:(id<MPModelChangeObserving>)observer {
|
||||
@@ -24,7 +29,47 @@ NSString *const MPModelChangeObservingKeyPathKey = @"MPModelChangeObservingKeyPa
|
||||
}
|
||||
|
||||
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath forTarget:(id)target {
|
||||
[MPModelChangeObservingHelper willChangeModelKeyPath:keyPath observer:target];
|
||||
[target setValue:value forKeyPath:keyPath];
|
||||
[MPModelChangeObservingHelper didChangeModelKeyPath:keyPath observer:target];
|
||||
}
|
||||
|
||||
- (void)beginObservingModelChangesForKeyPath:(NSString *)keyPath {
|
||||
if(!self.observedPaths) {
|
||||
self.observedPaths = [[NSMutableSet alloc] initWithCapacity:3];
|
||||
}
|
||||
[self.observedPaths addObject:keyPath];
|
||||
}
|
||||
|
||||
- (void)endObservingModelChangesForKeyPath:(NSString *)keyPath {
|
||||
[self.observedPaths removeObject:keyPath];
|
||||
/* if we have nothing to observer, just clear the cache and exit */
|
||||
if(self.observedPaths.count == 0) {
|
||||
self.matchedPathsCache = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
NSPredicate *predicat = [NSPredicate predicateWithBlock:^BOOL(id _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
|
||||
NSString *cachedPath = evaluatedObject;
|
||||
return ![cachedPath hasPrefix:keyPath];
|
||||
}];
|
||||
[self.matchedPathsCache filterUsingPredicate:predicat];
|
||||
}
|
||||
|
||||
- (BOOL)_isObservingKeyPath:(NSString *)keyPath {
|
||||
if([self.matchedPathsCache containsObject:keyPath]) {
|
||||
return YES;
|
||||
}
|
||||
for(NSString *observedKeyPath in self.observedPaths) {
|
||||
if([keyPath hasPrefix:observedKeyPath]) {
|
||||
if(!self.matchedPathsCache) {
|
||||
self.matchedPathsCache = [[NSMutableSet alloc] initWithCapacity:3];
|
||||
}
|
||||
[self.matchedPathsCache addObject:keyPath];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user