gpt4 book ai didi

cocoa - 如何重新加载链接到数组 Controller 的表格 View ?

转载 作者:行者123 更新时间:2023-12-03 18:00:12 25 4
gpt4 key购买 nike

我是 Cocoa 新手,我正在尝试创建一个应用程序来通过扫描 DHCP 服务器日志中的以太网硬件地址并记录最近的事务来审核我们的网络设备。我创建了一个基于文档的程序来执行此操作,并在绑定(bind)到数组 Controller 的 tableView 中显示其结果(可变字典的可变数组)。

我现在想要读取从网络 IPAM 管理器导出的文件,该文件包含分配给我们的虚拟 LAN 的以太网硬件地址列表,并将其与原始数组进行比较,添加缺少的设备并添加合适的注释。我已经通过文档上的按钮(readSecondFile)触发的操作来完成此操作。还有添加和删除按钮,用于进行手动输入,或者更有用的是,用于从列表中删除设备。还有一个用于导出编辑后的数组的保存例程。

除了一个异常(exception),一切正常。当读入第二个文件时,tableView 将不会重绘、重新加载其数据或执行其他操作,直到您使用 ArrayController 方法单击列标题进行排序或添加:或删除:。当发生这种情况时,附加条目会出现在 tableView 中。

我的问题是如何让 tableView 在 readSecondFile 例程末尾使用扩展数组重绘?我已经在使用 KeyValueObserving 了,但我不确定这是必需的,尽管它可以工作(如果我能让它工作的话!我已经要求 ArrayController 观察数组并通知数组的更改,但我'我不确定是否需要做更多。

有人可以帮忙吗?非常感谢。

[其他]刚刚注意到,它确实会重绘,因为它为阵列中的现有设备添加了一些注释,但它不显示具有 IPAM 条目但没有 DHCP 事件的其他设备。

[附加 - 请求代码]

//MyDocument.h
#import <Cocoa/Cocoa.h>
#import <stdio.h>
#import <regex.h>
#import <AppKit/AppKit.h>

typedef enum _dataFormat {
Unknown = 0,
PlainText = 1,
RichText = 2,
RTFD = 3,
} DataFormat;

int count, b, i, q, p;


@interface MyDocument : NSDocument
{
NSMutableArray *macs;
NSMutableDictionary *machines;
NSArray *filteredLines;
NSArray *lines;
IBOutlet NSTextField *processing;
IBOutlet NSProgressIndicator *myProgress;
IBOutlet NSButton *removeButton;
IBOutlet NSButton *readSecondFile;
IBOutlet NSTableView *tableView;
NSString *fileString;
}

-(IBAction)readSecondFileFromURL:(id)sender;

-(NSMutableArray *)macs;
-(NSMutableDictionary *)machines;
-(void)setMacs:(NSArray *)newMacs;
-(void)setMachines:(NSMutableDictionary *)newMachines;
-(NSArray *)filteredLines;
-(NSArray *)lines;


@end


// MyDocument.m

#import "MyDocument.h"
#import "dataArrayController.h"

@implementation MyDocument

- (id)init
{
self = [super init];
if (self) {
[self setMacs:[NSMutableArray array]];
}
//[dataArrayController bind:@"macs" // see update
// toObject:self
// withKeyPath:@"mac"
// options:0];

// set up an observer for arrangedObjects
[dataArrayController addObserver:self
forKeyPath:@"mac"
options:0
context:nil];

return self;
}

-(void)dealloc
{
[self setMacs:nil];
[super dealloc];
}

-(NSArray *)macs
{
return macs;
}

-(NSArray *)filteredLines
{
return filteredLines;
}

-(NSArray *)lines
{
return lines;
}

-(NSMutableDictionary *)machines
{
return machines;
}

-(void)setMacs:(NSMutableArray *)newMacs
{
[newMacs retain];
[macs release];
macs=newMacs;
//[macs setArray:newMacs];
}

-(void)setMachines:(NSMutableDictionary *)newMachines
{
[newMachines retain];
[machines release];
machines = newMachines;
[newMachines release];
}

-(void)setLines:(NSArray *)newLines
{
[newLines retain];
[filteredLines release];
filteredLines = newLines;
}

- (NSString *)windowNibName
{
return @"MyDocument";
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
[tableView reloadData];
}

-(BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError //Write a text file of the array (macs) contents
{
NSMutableString *csvString = [NSMutableString string];
NSEnumerator *macEnum = [macs objectEnumerator];
id data;
while (data = [macEnum nextObject] ){
NSNumber *mac = [data valueForKey:@"mac"];
NSNumber *ack = [data valueForKey:@"ack"];
NSString *vLan = [data valueForKey:@"vLan"];
[csvString appendString:[NSString stringWithFormat:@"%@,%@,%@\n", mac, ack, vLan]];
}
return [csvString writeToURL:absoluteURL atomically:NO encoding:NSUTF8StringEncoding error:outError];
}

-(BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError //Check the log file existance
{
fileString = [NSString stringWithContentsOfURL:absoluteURL encoding:NSUTF8StringEncoding error:outError];
if (nil == fileString) return NO;
return YES;
}

-(BOOL)readSecondFileFromURL:(id)sender //error:(NSError **)outError//(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError
{
double progress;
NSString* string = @"00:00:00:00:00:00";
NSString* pattern = @"[0-9A-Fa-f]{1,2}:[0-9A-Fa-f]{1,2}:[0-9A-Fa-f]{1,2}:[0-9A-Fa-f]{1,2}:[0-9A-Fa-f]{1,2}:[0-9A-Fa-f]{1,2}";
NSString* result = nil;
NSString* listItem = nil;
NSString* mac = nil;
NSArray* extracted = nil;
NSMutableDictionary* obj=nil;
NSDate *date = NULL;
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
[openDlg setCanChooseFiles:YES];
[openDlg setCanChooseDirectories:YES];

if ( [openDlg runModalForDirectory:nil file:nil] == NSOKButton )
{
NSArray* files = [openDlg filenames];
//NSLog(@"%@",[files description]);
// Loop through all the files and process them.
for( b = 0; b < [files count]; b++ )
{
extracted = [macs valueForKey:@"mac"];
//NSLog(@"%@", [extracted description]);
NSString* fileLoc = [files objectAtIndex:b];
//NSLog(@"%@",fileLoc);
fileString = [NSString stringWithContentsOfFile:fileLoc encoding:NSUTF8StringEncoding error:nil];
if (fileString == nil) return NO;

lines = [fileString componentsSeparatedByString:@"\n"]; // each line, adjust character for line endings
[processing setStringValue:@"Processing..."];
[processing display];

filteredLines = lines; //[lines filteredArrayUsingPredicate:pred];
count = [filteredLines count];
//NSLog(@"%d",count);
//NSLog(@"%@",[filteredLines description]);

[myProgress setDoubleValue:0.5];
[myProgress setIndeterminate:NO];
[myProgress displayIfNeeded];

i=0;
listItem = [[NSString alloc] initWithString: @""];

for (NSString *ent in filteredLines) {
string=ent;
result=NULL;
listItem=@"";
i++;
progress = 100*((double)i/(double)count);
q = progress;
//NSLog(@"%d",i);
if (q > p) {
[myProgress setDoubleValue:progress];
[myProgress displayIfNeeded];
p = q;
} //draw the progress bar
//NSLog(@"%@",string);
regex_t preg;
//NSLog(@"B:%@",string);
int err=regcomp(&preg,[pattern UTF8String],REG_EXTENDED);
if(err) {
char errbuf[256];
regerror(err,&preg,errbuf,sizeof(errbuf));
[NSException raise:@"CSRegexException"
format:@"Could not compile regex %@: %s",pattern,errbuf];
} //compile the regular expression
//NSLog(@"C:%@",string);

const char *cstr=[string UTF8String];
regmatch_t match;
if(regexec(&preg,cstr,1,&match,0)==0) {
result = [[[NSString alloc] initWithBytes:cstr+match.rm_so
length:match.rm_eo-match.rm_so encoding:NSUTF8StringEncoding] autorelease];
//NSLog(@"Result: %@",result);
} //pull out the ethernet hardware address by scanning for the regex
//NSLog(@"D:%@",result);
if(result != NULL){
if(result.length < 17) {
NSArray *listItems = [result componentsSeparatedByString:@":"];
for (NSString *bytepair in listItems){
//NSLog(@"split: %@", bytepair);
unsigned result;
if([[NSScanner scannerWithString: bytepair] scanHexInt: &result])
listItem=[listItem stringByAppendingFormat:@"%02x:", (int)result];
} //break address into array at colons
result=[listItem substringToIndex:17] ;
} //pad out to standard ethernet hardware address
mac = result;
//NSLog(@"%@ %d",mac, [extracted containsObject:mac]);
if ([extracted containsObject:mac]){
for(id key in macs) {
if ([[key valueForKey:@"mac"] isEqualToString:[NSString stringWithFormat:@"%@", mac]]) {
[key setValue:@"vLan OK" forKey:@"vLan"];
} //Check if the mac is already registered and if so annotate it.
} //Annotate an existing entry
} else {
date=[NSDate distantPast];
obj=[NSMutableDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"%@",mac], @"mac", date, @"ack", @"No DHCP activity", @"vLan", nil];
NSIndexSet *loneIndex = [NSIndexSet indexSetWithIndex:[macs count]];
[dataArrayController willChange:NSKeyValueChangeInsertion valuesAtIndexes:loneIndex forKey:@"mac"];
[macs addObject:obj];
[dataArrayController didChange:NSKeyValueChangeInsertion valuesAtIndexes:loneIndex forKey:@"mac"];
} //Add a new entry
}

}

//[myProgress setIndeterminate:YES];
//[myProgress startAnimation:self];
//[myProgress displayIfNeeded];
//NSLog(@"%@",[newMachines description]);
//[self setMachines:newMachines];
//NSLog(@"%@",[machines description]);
//mac = NULL;
//for (mac in machines) {
// ack = [machines valueForKey:mac];
// NSLog(@"F:%@", mac);
//[newMacs addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"%@",mac], @"mac", ack, @"ack", @"vLan", @"vLan", nil]];
//} //Convert the machine dictionary into a format suitable for an array controller
//[mac release];
//[machines release];
//[newMachines release];
//[self setMacs:newMacs];
//[dateFormat release];
//[myProgress setDisplayedWhenStopped:NO];
//[myProgress stopAnimation:self];
//[myProgress setHidden:YES];
//[processing setHidden:YES];
//if ([macs count]>0){
// [removeButton setHidden:NO];
//}
[readSecondFile setHidden:NO];
[readSecondFile display];
//[extracted release];
}
}

[tableView reloadData];

return YES;
}

- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{ [super windowControllerDidLoadNib:aController];
[self showWindows];
[removeButton setHidden:YES];
[removeButton display];
[readSecondFile setHidden:YES];
[readSecondFile display];
[processing setStringValue:@"Loading..."];
[processing setHidden:NO];
[processing display];
[myProgress setHidden:NO];
[myProgress setUsesThreadedAnimation:YES];
[myProgress setIndeterminate:YES];
[myProgress startAnimation:self];

int count, i, q, p;
double progress;

NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF CONTAINS 'DHCP'"];

NSString* string = @"00:00:00:00:00:00";
NSString* pattern = @"[0-9A-Fa-f]{1,2}:[0-9A-Fa-f]{1,2}:[0-9A-Fa-f]{1,2}:[0-9A-Fa-f]{1,2}:[0-9A-Fa-f]{1,2}:[0-9A-Fa-f]{1,2}";
NSString* result = nil;
NSString* listItem = nil;
NSString* mac = nil;
NSString* ack = nil;
NSString* localeDetect = nil;
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; // Convert string to date object
NSDate *date = NULL;
NSRange rangeForLocaleDetect = NSMakeRange (20, 3);
NSMutableArray *newMacs = [NSMutableArray array];

lines = [fileString componentsSeparatedByString:@"\n"]; // each line, adjust character for line endings
[processing setStringValue:@"Processing..."];
[processing display];

filteredLines = [lines filteredArrayUsingPredicate:pred];
count = [filteredLines count];

NSMutableDictionary *newMachines = [NSMutableDictionary dictionaryWithCapacity:count];

[myProgress setDoubleValue:0.5];
[myProgress setIndeterminate:NO];
[myProgress displayIfNeeded];

i=0;
p=0;

for (NSString *ent in filteredLines) {
string=ent;
i++;
progress = 100*((double)i/(double)count);
q = progress;
if (q > p) {
[myProgress setDoubleValue:progress];
[myProgress displayIfNeeded];
p = q;
} //draw the progress bar

listItem = [[NSString alloc] initWithString: @""];
localeDetect = [NSString stringWithFormat:@"%@",[string substringWithRange:rangeForLocaleDetect]];

if ([localeDetect isEqualToString:@"UTC"]){
[dateFormat setDateFormat:@"yyyy.MM.dd HH:mm:ss"];
ack = [NSString stringWithFormat:@"%@", [string substringToIndex:19]];
} else {
[dateFormat setDateFormat:@"MMM dd HH:mm:ss"];
ack = [NSString stringWithFormat:@"%@",[string substringToIndex:15]];

}

date = [dateFormat dateFromString:ack];
regex_t preg;
int err=regcomp(&preg,[pattern UTF8String],REG_EXTENDED);
if(err) {
char errbuf[256];
regerror(err,&preg,errbuf,sizeof(errbuf));
[NSException raise:@"CSRegexException"
format:@"Could not compile regex %@: %s",pattern,errbuf];
} //compile the regular expression

const char *cstr=[string UTF8String];
regmatch_t match;
if(regexec(&preg,cstr,1,&match,0)==0) {
result = [[[NSString alloc] initWithBytes:cstr+match.rm_so
length:match.rm_eo-match.rm_so encoding:NSUTF8StringEncoding] autorelease];
} //pull out the ethernet hardware address by scanning for the regex

if(result.length < 17) {
NSArray *listItems = [result componentsSeparatedByString:@":"];
for (NSString *bytepair in listItems){
//NSLog(@"split: %@", bytepair);
unsigned result;
if([[NSScanner scannerWithString: bytepair] scanHexInt: &result])
listItem=[listItem stringByAppendingFormat:@"%02x:", (int)result];
} //break address into array at colons
result=[listItem substringToIndex:17] ;
} //pad out to standard ethernet hardware address

mac = result;
NSDate *old = [newMachines valueForKey:mac];
if (([date laterDate:old]==date) || old==NULL){
[newMachines setValue:date forKey:mac];
} //Check for and compare dates for existing keys, as the log file might just be out of sequence
} //For every line in the log which meets the Predicate, extract the relevant information.

[myProgress setIndeterminate:YES];
[myProgress startAnimation:self];
[myProgress displayIfNeeded];

[self setMachines:newMachines];

for (mac in machines) {
ack = [machines valueForKey:mac];
[newMacs addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"%@",mac], @"mac", ack, @"ack", @"", @"vLan", nil]];
} //Convert the machine dictionary into a format suitable for an array controller

[self setMacs:newMacs];
[dateFormat release];

[myProgress setDisplayedWhenStopped:NO];
[myProgress stopAnimation:self];
[myProgress setHidden:YES];
[processing setHidden:YES];
if ([macs count]>0){
[removeButton setHidden:NO];
}
[readSecondFile setHidden:NO];
[readSecondFile display];


} //Process the file and display the relevant progress bars. Create and populate array.

- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
{
// Insert code here to write your document to data of the specified type. If the given outError != NULL, ensure that you set *outError when returning nil.
// You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
// For applications targeted for Panther or earlier systems, you should use the deprecated API -dataRepresentationOfType:. In this case you can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.

if ( outError != NULL ) {
*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
}
return nil;
}

- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
// Insert code here to read your document from the given data of the specified type. If the given outError != NULL, ensure that you set *outError when returning NO.
// You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead.
// For applications targeted for Panther or earlier systems, you should use the deprecated API -loadDataRepresentation:ofType. In this case you can also choose to override -readFromFile:ofType: or -loadFileWrapperRepresentation:ofType: instead.

if ( outError != NULL ) {
*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
}
return YES;
}

@end

最佳答案

正确的方法是使用ArrayController将新对象添加到tableView正在显示的数组中。

ArrayController 没有响应这些方法,因为我在开发工作期间对其进行了子类化,并且后来无意中没有删除该子类化。事实证明,noa 的评论对于促使我重新检查我的代码非常有值(value)。非常感谢。

关于cocoa - 如何重新加载链接到数组 Controller 的表格 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7766105/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com