【问题标题】:Cocoa app scrolling slow when window on focus, fast when not可可应用程序在窗口聚焦时滚动缓慢,而不是快速滚动
【发布时间】:2016-10-27 20:43:33
【问题描述】:

我有一个包含 NSTableView 的窗口的可可应用程序。每行有几列、三个单选框和两个按钮。目前该表格有 260 行,当窗口聚焦时,表格视图中的滚动非常缓慢且不稳定。当窗口没有聚焦并且我将鼠标悬停在表格视图上并滚动它时,它非常光滑。

我尝试通过更改背景绘图和启用 CoreAnimation Layer 来解决性能缓慢的问题,但无济于事。

为什么当窗口没有焦点时滚动会很快,而当它有焦点时滚动很慢?

我只是对为什么滚动如此缓慢感到困惑。

这是我的 ProposalTableViewController.h

#import <Cocoa/Cocoa.h>
#import <Foundation/Foundation.h>
#import <QuickLook/QuickLook.h>
#import <Quartz/Quartz.h>

@interface ProposalTableViewController : NSObject<NSTableViewDataSource, NSTableViewDelegate, QLPreviewPanelDelegate, QLPreviewPanelDataSource>{
@public
    NSMutableArray *list;
    IBOutlet NSTableView *tableView;
    IBOutlet NSSearchField *searchText;
    IBOutlet NSTextField *countTextField;
}

@property (strong) QLPreviewPanel *previewPanel;

+ (ProposalTableViewController *)getInstance;

- (IBAction)deleteRow:(id)sender;
- (IBAction)exportData:(id)sender;
- (void)loadData;
- (void)countItems;

@end

还有我的 ProposalTableViewController.m

#import "ProposalTableViewController.h"
#import "Proposal.h"
#import "StatusRadioView.h"
#import "DBManager.h"
#import "filePathButtonView.h"
#import <Quartz/Quartz.h>
#import "AppDelegate.h"
@implementation Proposal (QLPreviewItem)

- (NSURL *)previewItemURL
{
    return [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@.pdf",self.filePath]];
}

- (NSString *)previewItemTitle
{
    return [NSString stringWithFormat:@"Proposal %@",self.proposalNumber];
}

@end

@implementation ProposalTableViewController

static ProposalTableViewController *instance;
+ (ProposalTableViewController *)getInstance{
    return instance;
}

//------------------------------------------------------------------------------------------------------------------------------------
//                                                      Init
//------------------------------------------------------------------------------------------------------------------------------------
- (id)init{
    self = [super init];
    if(self){
        instance = self;

        list = [[NSMutableArray alloc] init];
        [self loadData];

        for (NSTableColumn *tableColumn in tableView.tableColumns ) {
            NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:tableColumn.identifier ascending:YES selector:@selector(compare:)];
            [tableColumn setSortDescriptorPrototype:sortDescriptor];
        }
    }
    return self;
}
//------------------------------------------------------------------------------------------------------------------------------------
//                                                      Load Data from SQLite
//------------------------------------------------------------------------------------------------------------------------------------
- (void)loadData {
    list = [[DBManager getProposalTable] select:@""];
    NSSortDescriptor* desc = [[NSSortDescriptor alloc] initWithKey:@"proposalNumber" ascending:NO selector:@selector(compare:)];
    [list sortUsingDescriptors:[NSArray arrayWithObjects:desc, nil]];
    [tableView reloadData];
    [self countItems: list];
}
//------------------------------------------------------------------------------------------------------------------------------------
//                                                      Number of Rows in Table View
//------------------------------------------------------------------------------------------------------------------------------------
- (NSInteger) numberOfRowsInTableView:(NSTableView *)tableView {
    return [list count];
}

-(void)countItems:(NSArray *)list; {
    NSString *countText;
    int size = [list count];
    if (size == 1){
        countText = @"item in list";
    }else{
        countText = @"items in list";
    }
    NSString *itemCount = [NSString stringWithFormat:@"%d %@", size, countText];
    [countTextField setStringValue:itemCount];
}
//------------------------------------------------------------------------------------------------------------------------------------
//                                                      Get View for Table Column
//------------------------------------------------------------------------------------------------------------------------------------
- (NSView *)tableView:(NSTableView *)table_view viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    Proposal *p = [list objectAtIndex:row];
    NSString *identifier = [tableColumn identifier];
    NSString *holdingValue;

    NSTableCellView *cell = [table_view makeViewWithIdentifier:identifier owner:self];
    if([identifier isEqualToString:@"status"]){
        StatusRadioView *radioView = [[StatusRadioView alloc] initWithProposal:p];
        return radioView;
    }else if ([identifier isEqualToString:@"filePath"]){
        filePathButtonView *buttonView = [[filePathButtonView alloc]initWithProposal:p];
        return buttonView;
    }else if ([identifier isEqualToString:@"clientAccessPoint"]){
        holdingValue = [p valueForKey:identifier];
            if (!holdingValue){
                cell.textField.stringValue = @"N/A";
            }else{
                cell.textField.stringValue = [p valueForKey:identifier];
            }
    }else{
    cell.textField.stringValue = [p valueForKey:identifier];
    }
    return cell;
}

//------------------------------------------------------------------------------------------------------------------------------------
//                                                      Sort Descriptors did Change
//------------------------------------------------------------------------------------------------------------------------------------
-(void)tableView:(NSTableView *)mtableView sortDescriptorsDidChange:(NSArray *)oldDescriptors {
    [list sortUsingDescriptors: [mtableView sortDescriptors]];
    [tableView reloadData];
}
//table row height
-(CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row {
    return 25;
}
//------------------------------------------------------------------------------------------------------------------------------------
//                                                      Search Text did Change
//------------------------------------------------------------------------------------------------------------------------------------
- (void)controlTextDidChange:(NSNotification *)notification {
    NSSortDescriptor* desc = [[NSSortDescriptor alloc] initWithKey:@"proposalNumber" ascending:NO selector:@selector(compare:)];
    NSTextField *textField = [notification object];
    NSString *str = [textField stringValue];
    list = [[DBManager getProposalTable] select:str];
    [list sortUsingDescriptors:[NSArray arrayWithObjects:desc, nil]];
    [tableView reloadData];
    [self countItems: list];
}
//------------------------------------------------------------------------------------------------------------------------------------
//                                                      Export DATA
//------------------------------------------------------------------------------------------------------------------------------------
- (IBAction)exportData:(id)sender{
    NSString *content = @"";
    for(Proposal *p in list){
        NSString *row = [NSString stringWithFormat:@"%@,%@,%@,%@,%@,%@,%@,%@,%@,%@", p.proposalNumber,p.itemNumber,p.clientName,p.medium,p.support,p.cost,p.dateCreated,p.status,p.dateStatusChanged,p.clientAccessPoint];
        row = [row stringByReplacingOccurrencesOfString:@"\n" withString:@""];
        row = [NSString stringWithFormat:@"%@\n", row];
        content = [content stringByAppendingString:row];
    }
    //get the documents directory:
    NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Baumgartner Fine Art Restoration"];
    NSString *fileName = [documentsDirectory stringByAppendingPathComponent:@"proposalBuilderDatabase.csv"];

    [[NSFileManager defaultManager] createDirectoryAtPath:documentsDirectory
                              withIntermediateDirectories:NO
                                               attributes:nil
                                                    error:nil];
    [content writeToFile:fileName
              atomically:NO
                encoding:NSStringEncodingConversionAllowLossy
                   error:nil];

    NSAlert *alert = [[NSAlert alloc] init];
    [alert setMessageText:@"Export Succeeded"];
    [alert addButtonWithTitle:@"Ok"];
    [alert runModal];
}
//------------------------------------------------------------------------------------------------------------------------------------
//                                                      Delete row from DB and table
//------------------------------------------------------------------------------------------------------------------------------------
- (IBAction)deleteRow:(id)sender{
    NSString *row = list[tableView.selectedRow];
    NSString *mid = [row valueForKey:@"m_id"];

    ProposalTable *deleteRow = [[ProposalTable alloc] init];

    [deleteRow deleteWithId: mid];
    [self loadData];
    [tableView reloadData];
}
//------------------------------------------------------------------------------------------------------------------------------------
//                                                      QuickLook
//------------------------------------------------------------------------------------------------------------------------------------
- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel {
    return [list count];
}

- (id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index {
    return list[tableView.selectedRow];
}

- (BOOL)previewPanel:(QLPreviewPanel *)panel handleEvent:(NSEvent *)event {
    // redirect all key down events to the table view
    if ([event type] == NSKeyDown) {
        [tableView keyDown:event];
        return YES;
    }
    return NO;
}

// This delegate method provides the rect on screen from which the panel will zoom.
- (NSRect)previewPanel:(QLPreviewPanel *)panel sourceFrameOnScreenForPreviewItem:(id <QLPreviewItem>)item {
    return NSZeroRect;
}

- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)rowIndex {
    [[QLPreviewPanel sharedPreviewPanel]reloadData];
    return YES;
}
@end

这是我的 ProposalTableView.h

#import <Cocoa/Cocoa.h>

@interface ProposalTableView : NSTableView

@end

还有我的 ProposalTableView.m

#import "ProposalTableView.h"
#import "AppDelegate.h"
@implementation ProposalTableView

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];
    self.wantsLayer = YES;

    // Drawing code here.
}


- (void)keyDown:(NSEvent *)theEvent
{
    NSString *key = [theEvent charactersIgnoringModifiers];
    if ([key isEqual:@" "])
    {
        [[NSApp delegate] togglePreviewPanel:self];
    }
    else
    {
        [super keyDown:theEvent];
    }
}
@end

还有一些代码可以建立 SqLite DB 连接并与 DB 交互以获取记录或删除等...但这并不是真正需要的...我也有绘制单选按钮和其他按钮的代码但是再说一次,我认为这没有必要,除非有人认为绘图正在造成减速......?

【问题讨论】:

  • 你能给我们看一些代码吗?你使用NSScrollViewDelegate 方法吗?请提供您的控制器代码。
  • @Astoria NSScrollView 没有代表。
  • @Willeke 你是对的,它没有。我的意思是NSViewBoundsDidChangeNotification-notification 的一些回调方法。
  • 编辑添加了一些代码...感谢您的关注!

标签: macos cocoa


【解决方案1】:

所以事实证明,单选按钮的绘制是导致减速的原因......回到绘图板。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    • 2019-11-25
    • 2017-09-05
    • 2012-04-27
    • 2011-09-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多