我刚刚开始使用 Core Plot,并且为了测试,将 CPTGraphHostingView 嵌入到一个简单的自定义 View Controller 中,绘制来自 Core Data fetchRequest 的值(这是一个绘制每日饮食卡路里摄入量的应用程序).
代码大部分是从教程中粘贴的 here .
问题是将 View Controller 插入 View (它嵌入在导航 Controller 中)时,UI 卡住了大约两秒钟。这是在设备 (iPhone 4S) 上运行时的情况。
Instruments 中的分析显示主线程被 [CPTAxis layoutSublayers] 和 [CPTLayer drawInContext] 阻塞。
滞后不是由于数据集过大:它目前恰好包含两个点。该图非常简单,看起来像这样:
View Controller 的完整实现:
接口(interface):
//
// 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)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)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)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)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 *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)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 代码无关;一切正常。谷歌搜索只会显示庞大数据集的问题,而不是只有两点的问题。显然我在 Core Plot 代码上做了一些根本性的错误,但我真的看不出是什么。
有人能发现问题吗?
最佳答案
maxDailyCaloriesInDataset 大吗?默认的轴标签策略将刻度线和标签沿轴分开一个单位。如果 yRange 很大,就会产生很多重叠的标签,这会非常慢。根据您应用的要求,增加 majorIntervalLength 以减少标签数量,或者更改标签政策。 CPTAxisLabelingPolicyAutomatic 和 CPTAxisLabelingPolicyEqualDivisions 将是不错的选择。
关于ios - 加载包含 Core Plot 图的 View Controller 时延迟过大,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18404887/
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
我的Gallery模型中有以下查询:media_items.includes(:photo,:video).rank(:position_in_gallery)我的图库模型有_许多媒体项,每个都有一个照片或视频关联。到目前为止,一切正常。它返回所有media_items包括它们的photo或video关联,由media_item的position_in_gallery属性排序。但是我现在需要将此查询返回的照片限制为仅具有is_processing属性的照片,即nil。是否可以进行相同的查询,但条件是返回的照片等同于:.where(photo:'photo.is_processingIS