• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ios - 加载包含 Core Plot 图的 View Controller 时延迟过大

[复制链接]
菜鸟教程小白 发表于 2022-12-12 13:46:08 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我刚开始使用 Core Plot,为了测试,在一个简单的自定义 View Controller 中嵌入了一个 CPTGraphHostingView,绘制来自 Core Data fetchRequest 的值(这是一个绘制每天膳食卡路里摄入量的应用程序)。

代码大部分是从教程 here 中粘贴的.

问题是当将 View Controller 插入 View 时 UI 卡住了大约两秒钟(它嵌入在导航 Controller 中)。这是在设备 (iPhone 4S) 上运行时。

Instruments 中的分析显示主线程被 [CPTAxis layoutSublayers][CPTLayer drawInContext] 阻塞。

延迟不是由于数据集过大:它目前正好包含两个点。该图非常简单,如下所示:

enter image description here

View Controller 的完整实现:​​

界面:

//
//  ICCaloriesGraphController.h
//  iCalories
//
//  Created by David Fearon on 22/08/2013.
//  Copyright (c) 2013 David Fearon. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "CorePlot-CocoaTouch.h"
#import "ICDatabaseBrain.h"
#import "Day.h"
#import "CalorieEntry.h"

@interface ICCaloriesGraphController : UIViewController<CPTPlotDataSource, NSFetchedResultsControllerDelegate>
@property (weak, nonatomic) IBOutlet CPTGraphHostingView *graphHostingView;
@property (nonatomic, retain)ICDatabaseBrain* sharedDatabaseBrain;
@property (nonatomic, retain)NSFetchedResultsController* resultsController;

@end

实现:

//
//  ICCaloriesGraphController.m
//  iCalories
//
//  Created by David Fearon on 22/08/2013.
//  Copyright (c) 2013 David Fearon. All rights reserved.
//

#import "ICCaloriesGraphController.h"

@interface ICCaloriesGraphController ()

@property int numberOfRecordsForPlot;
@property float maxDailyCaloriesInDataset;
@property NSArray* days;

@end

@implementation ICCaloriesGraphController

- (id)initWithNibNameNSString *)nibNameOrNil bundleNSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.sharedDatabaseBrain = [ICDatabaseBrain sharedDatabaseBrain];
    self.resultsController = self.sharedDatabaseBrain.fetchDaysResultsController;

    self.days = [self.resultsController fetchedObjects];
    self.numberOfRecordsForPlot = [self.days count];

    [self updateMaxDailyCaloriesInDataset];

    // Create a CPTGraph object and add to hostView
    CPTGraph* graph = [[CPTXYGraph alloc] initWithFrame:self.graphHostingView.bounds];
    self.graphHostingView.hostedGraph = graph;

    // Get the (default) plotspace from the graph so we can set its x/y ranges
    CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) self.graphHostingView.hostedGraph.defaultPlotSpace;

    // Note that these CPTPlotRange are defined by START and LENGTH (not START and END) !!
    [plotSpace setYRange: [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat( 0 ) length:CPTDecimalFromFloat( self.maxDailyCaloriesInDataset )]];
    [plotSpace setXRange: [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat( 0 ) length:CPTDecimalFromFloat( self.numberOfRecordsForPlot )]];

    // Create the plot (we do not define actual x/y values yet, these will be supplied by the datasource...)
    CPTScatterPlot* plot = [[CPTScatterPlot alloc] initWithFrame:CGRectZero];

    // Let's keep it simple and let this class act as datasource (therefore we implement <CPTPlotDataSource>)
    plot.dataSource = self;

    // Finally, add the created plot to the default plot space of the CPTGraph object we created before
    [self.graphHostingView.hostedGraph addPlot:plot toPlotSpace:self.graphHostingView.hostedGraph.defaultPlotSpace];

}

-(void)viewWillAppearBOOL)animated{

    [super viewWillAppear:animated];

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


-(NSUInteger)numberOfRecordsForPlotCPTPlot *)plotnumberOfRecords {
    return self.numberOfRecordsForPlot;
}


-(void)updateMaxDailyCaloriesInDataset{

    if (self.numberOfRecordsForPlot == 0){
        self.maxDailyCaloriesInDataset = 0;
        return;
    }

    int max = 0;

    for (Day* day in self.days) {

        //count the calories in the day:
        int calorieSum = 0;
        for (CalorieEntry* calorieEntry in [day.calorieEntries allObjects]) {
            calorieSum += calorieEntry.calories.intValue;
        }

        if(calorieSum > max) max = calorieSum;

    }

    self.maxDailyCaloriesInDataset = max;

}


-(NSNumber *)numberForPlotCPTPlot *)plot fieldNSUInteger)fieldEnum recordIndexNSUInteger)index
{

    if (self.numberOfRecordsForPlot == 0){
        return 0;
    }

    if(fieldEnum == CPTScatterPlotFieldY){

        Day* day = [self.days objectAtIndex:index];

        //count the calories in the day:
        int calorieSum = 0;
        for (CalorieEntry* calorieEntry in [day.calorieEntries allObjects]) {
            calorieSum += calorieEntry.calories.intValue;
        }

        return [NSNumber numberWithInt:calorieSum];
        //TODO: Set range for y axis

    }

    if(fieldEnum == CPTScatterPlotFieldX){
        return [NSNumber numberWithInt: index];
    }else{
        NSLog(@"fieldEnum was neither CPTScatterPlotFieldY or CPTScatterPlotFieldX in numberForPlot:");
        return 0;
    }

}

@end

延迟绝对与 Core Data 代码无关;一切正常。谷歌搜索只会显示大型数据集的问题,而不是只有两点的问题。显然,我对核心情节代码做了一些根本性的错误,但真的看不出是什么。

请问有人能发现问题吗?



Best Answer-推荐答案


maxDailyCaloriesInDataset 大吗?默认轴标签策略将刻度标记和标签沿轴分开一个单位。如果 yRange 很大,这会创建很多重叠的标签,这可能会非常慢。根据您的应用程序的要求,增加 majorIntervalLength 使其不会制作这么多标签,或者更改标签策略。 CPTAxisLabelingPolicyAutomaticCPTAxisLabelingPolicyEqualDivisions 会是不错的选择。

关于ios - 加载包含 Core Plot 图的 View Controller 时延迟过大,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18404887/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap