The goal is to create an infinite chessboard pattern.
Using a SCNFloor and the attached image, we produce something close but not quite like a chessboard. Some black squares merge where they shouldn't.
We tried different values for Scale, WrapS, WrapT, Min filter, Map filter, and Mip filter. The screenshot shows the current values.
Is the underlying image not correct, or what setting do we need to change for the SCNFloor?
Repeated image:
Result:
#import "GameViewController.h"
#interface GameViewController ()
#property (nonatomic) CGFloat chessBoardWidth;
#property (nonatomic) CGFloat chessBoardDepth;
#property (nonatomic) CGFloat tileWidth;
#property (nonatomic) CGFloat tileDepth;
#property (nonatomic, getter=isOdd) BOOL odd;
#end
#implementation GameViewController
-(instancetype)init {
self = [super init];
if(self) {
self.chessBoardWidth = 10.0f;
self.chessBoardDepth = 10.0f;
self.tileWidth = 1.0f;
self.tileDepth = 1.0f;
}
return self;
}
-(void)awakeFromNib
{
[super awakeFromNib];
// create a new scene
SCNScene *scene = [SCNScene sceneNamed:#"art.scnassets/chessboard.scn"];
// create and add a camera to the scene
SCNNode *cameraNode = [SCNNode node];
cameraNode.camera = [SCNCamera camera];
[scene.rootNode addChildNode:cameraNode];
// place the camera
cameraNode.position = SCNVector3Make(0, 0, 150);
// create and add a light to the scene
SCNNode *lightNode = [SCNNode node];
lightNode.light = [SCNLight light];
lightNode.light.type = SCNLightTypeOmni;
lightNode.position = SCNVector3Make(0, 10, 10);
[scene.rootNode addChildNode:lightNode];
// create and add an ambient light to the scene
SCNNode *ambientLightNode = [SCNNode node];
ambientLightNode.light = [SCNLight light];
ambientLightNode.light.type = SCNLightTypeAmbient;
ambientLightNode.light.color = [NSColor darkGrayColor];
[scene.rootNode addChildNode:ambientLightNode];
// Material
SCNMaterial *blackMaterial = [SCNMaterial material];
blackMaterial.diffuse.contents = [NSColor blackColor];
SCNMaterial *whiteMaterial = [SCNMaterial material];
whiteMaterial.diffuse.contents = [NSColor whiteColor];
// Geometry
SCNPlane *blackTile = [[SCNPlane alloc] init];
blackTile.firstMaterial = blackMaterial;
SCNPlane *whiteTile = [[SCNPlane alloc] init];
whiteTile.firstMaterial = whiteMaterial;
// Parent node
SCNNode *parentNode = [[SCNNode alloc] init];
[scene.rootNode addChildNode:parentNode];
self.odd = YES;
for (uint x=0; x < self.chessBoardWidth; x++) {
for (uint z=0; z < self.chessBoardDepth; z++) {
// Add tile
SCNNode *tileNode = [[SCNNode alloc] init];
if(self.isOdd) {
tileNode.geometry = blackTile;
} else {
tileNode.geometry = whiteTile;
}
[parentNode addChildNode:tileNode];
// Position tile
tileNode.position = SCNVector3Make(self.tileWidth * x, 0, self.tileDepth * z);
// Alternate
if(self.isOdd) {
self.odd = NO;
} else {
self.odd = YES;
}
}
}
// set the scene to the view
self.gameView.scene = scene;
// allows the user to manipulate the camera
self.gameView.allowsCameraControl = YES;
// show statistics such as fps and timing information
self.gameView.showsStatistics = YES;
// configure the view
self.gameView.backgroundColor = [NSColor grayColor];
}
#end
Related
I'm working with core plot on xCode and I want to plot some real-time incoming data via bluetooth.
I used the CPTTestAPP for Mac Os X as example and tried to adapt it to my specific case.
The first 60 points are added like it's supposed to and due the following unaltered code:
-(void)setupScatterPlots
{
static BOOL hasData = NO;
// Create one plot that uses bindings
CPTScatterPlot *boundLinePlot = [[CPTScatterPlot alloc] init];
boundLinePlot.identifier = bindingsPlot;
CPTMutableLineStyle *lineStyle = [boundLinePlot.dataLineStyle mutableCopy];
lineStyle.miterLimit = 1.0;
lineStyle.lineWidth = 2.0;
lineStyle.lineColor = [CPTColor redColor];
boundLinePlot.dataLineStyle = lineStyle;
[self.graph addPlot:boundLinePlot];
[boundLinePlot bind:CPTScatterPlotBindingXValues toObject:self withKeyPath:#"arrangedObjects.x" options:nil];
[boundLinePlot bind:CPTScatterPlotBindingYValues toObject:self withKeyPath:#"arrangedObjects.y" options:nil];
// Set plot delegate, to know when symbols have been touched
// We will display an annotation when a symbol is touched
boundLinePlot.delegate = self;
boundLinePlot.plotSymbolMarginForHitDetection = 5.0;
if ( !hasData ) {
// Add some initial data
contentArray = [NSMutableArray arrayWithCapacity:100];
for ( NSUInteger i = 0; i < 60; i++ ) {
NSNumber *x = #(1.0 + i * 0.05);
NSNumber *y = #(1.2 * arc4random() / (double)UINT32_MAX + 1.2);
[contentArray addObject:#{ #"x": x,
#"y": y }
];
}
self.content = contentArray;
hasData = YES;
}
// Auto scale the plot space to fit the plot data
// Extend the y range by 10% for neatness
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)self.graph.defaultPlotSpace;
plotSpace.allowsMomentum = YES;
[plotSpace scaleToFitPlots:#[boundLinePlot]];
CPTPlotRange *xRange = plotSpace.xRange;
CPTMutablePlotRange *yRange = [plotSpace.yRange mutableCopy];
[yRange expandRangeByFactor:CPTDecimalFromDouble(1.1)];
plotSpace.yRange = yRange;
// Restrict y range to a global range
plotSpace.globalXRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-1.0) length:CPTDecimalFromDouble(10.0)];
plotSpace.globalYRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-1.0) length:CPTDecimalFromDouble(5.0)];
// set the x and y shift to match the new ranges
CGFloat length = xRange.lengthDouble;
self.xShift = length - 3.0;
length = yRange.lengthDouble;
self.yShift = length - 2.0;
}
I'm using a method called insertData who looks like this:
-(void)insertData:(uint32 *) buf :(uint32 *) i
{
[contentArray addObject:#{ #"x": i,
#"y": buf }
];
NSLog(#"%#",contentArray);
self.content = contentArray;
}
where buf is my incoming data.
But when I call the insertData method, the data are appended to the array but the tab on my interface doesn't change, neither does the plot.
can anyone help me please?
thanks !
I already tried to convert the int to NSNumber by using the following :
NSNumber *ni = #(*i);
NSNumber *nbuf = #(*buf);
and:
NSNumber *ni = [NSNumber numberWithUnsignedInt:(*i);
NSNumber *nbuf = [NSNumber numberWithUnsignedInt:(*buf);
I also tried all the reload stuff I found over the internet
but none of that worked either.
#import "Controller.h"
#import "HeartRateMonitorAppDelegate.h"
static const CGFloat kZDistanceBetweenLayers = 20.0;
static NSString *const bindingsPlot = #"Bindings Plot";
static NSMutableArray *contentArray;
#interface Controller()
#property (nonatomic, readwrite, strong) IBOutlet CPTGraphHostingView *hostView;
#property (nonatomic, readwrite, strong) CPTXYGraph *graph;
#property (nonatomic, readwrite, strong) CPTPlotSpaceAnnotation *symbolTextAnnotation;
-(void)setupGraph;
-(void)setupAxes;
-(void)setupScatterPlots;
#end
#pragma mark -
#implementation Controller
#synthesize hostView;
#synthesize graph;
#synthesize symbolTextAnnotation;
+(void)initialize
{
[NSValueTransformer setValueTransformer:[CPTDecimalNumberValueTransformer new] forName:#"CPTDecimalNumberValueTransformer"];
}
-(void)awakeFromNib
{
[super awakeFromNib];
self.xShift = 0.0;
self.yShift = 0.0;
[self setupGraph];
[self setupAxes];
[self setupScatterPlots];
}
-(id)newObject:(uint32 *) buf :(uint32 *) i
{
NSLog(#"buf = %d", *buf);
NSNumber *x1 = #(*i);
NSNumber *y1 = #(*i);
return #{
#"x": x1,
#"y": y1
};
}
#pragma mark -
#pragma mark Graph Setup Methods
-(void)setupGraph
{
// Create graph and apply a dark theme
CPTXYGraph *newGraph = [[CPTXYGraph alloc] initWithFrame:NSRectToCGRect(self.hostView.bounds)];
CPTTheme *theme = [CPTTheme themeNamed:kCPTDarkGradientTheme];
[newGraph applyTheme:theme];
self.hostView.hostedGraph = newGraph;
self.graph = newGraph;
// Graph padding
newGraph.paddingLeft = 0.0;
newGraph.paddingTop = 0.0;
newGraph.paddingRight = 0.0;
newGraph.paddingBottom = 0.0;
// Plot area delegate
newGraph.plotAreaFrame.plotArea.delegate = self;
}
-(void)setupAxes
{
// Setup scatter plot space
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)self.graph.defaultPlotSpace;
plotSpace.allowsUserInteraction = YES;
plotSpace.delegate = self;
// Grid line styles
CPTMutableLineStyle *majorGridLineStyle = [CPTMutableLineStyle lineStyle];
majorGridLineStyle.lineWidth = 0.75;
majorGridLineStyle.lineColor = [[CPTColor colorWithGenericGray:0.2] colorWithAlphaComponent:0.75];
CPTMutableLineStyle *minorGridLineStyle = [CPTMutableLineStyle lineStyle];
minorGridLineStyle.lineWidth = 0.25;
minorGridLineStyle.lineColor = [[CPTColor whiteColor] colorWithAlphaComponent:0.1];
CPTMutableLineStyle *redLineStyle = [CPTMutableLineStyle lineStyle];
redLineStyle.lineWidth = 10.0;
redLineStyle.lineColor = [[CPTColor redColor] colorWithAlphaComponent:0.5];
// Axes
// Label x axis with a fixed interval policy
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)self.graph.axisSet;
CPTXYAxis *x = axisSet.xAxis;
x.majorIntervalLength = CPTDecimalFromDouble(0.5);
x.orthogonalCoordinateDecimal = CPTDecimalFromDouble(0.0);
x.minorTicksPerInterval = 2;
x.majorGridLineStyle = majorGridLineStyle;
x.minorGridLineStyle = minorGridLineStyle;
NSArray *exclusionRanges = #[[CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(1.99) length:CPTDecimalFromDouble(0.02)],
[CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0.99) length:CPTDecimalFromDouble(0.02)],
[CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(2.99) length:CPTDecimalFromDouble(0.02)]];
x.labelExclusionRanges = exclusionRanges;
// Label y with an automatic label policy.
CPTXYAxis *y = axisSet.yAxis;
y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
y.orthogonalCoordinateDecimal = CPTDecimalFromDouble(0.0);
y.minorTicksPerInterval = 2;
y.preferredNumberOfMajorTicks = 8;
y.majorGridLineStyle = majorGridLineStyle;
y.minorGridLineStyle = minorGridLineStyle;
y.labelOffset = 10.0;
exclusionRanges = #[[CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(1.99) length:CPTDecimalFromDouble(0.02)],
[CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0.99) length:CPTDecimalFromDouble(0.02)],
[CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(3.99) length:CPTDecimalFromDouble(0.02)]];
y.labelExclusionRanges = exclusionRanges;
}
-(void)setupScatterPlots
{
static BOOL hasData = NO;
// Create one plot that uses bindings
CPTScatterPlot *boundLinePlot = [[CPTScatterPlot alloc] init];
boundLinePlot.identifier = bindingsPlot;
CPTMutableLineStyle *lineStyle = [boundLinePlot.dataLineStyle mutableCopy];
lineStyle.miterLimit = 1.0;
lineStyle.lineWidth = 2.0;
lineStyle.lineColor = [CPTColor redColor];
boundLinePlot.dataLineStyle = lineStyle;
[self.graph addPlot:boundLinePlot];
[boundLinePlot bind:CPTScatterPlotBindingXValues toObject:self withKeyPath:#"arrangedObjects.x" options:nil];
[boundLinePlot bind:CPTScatterPlotBindingYValues toObject:self withKeyPath:#"arrangedObjects.y" options:nil];
// Set plot delegate, to know when symbols have been touched
// We will display an annotation when a symbol is touched
boundLinePlot.delegate = self;
boundLinePlot.plotSymbolMarginForHitDetection = 5.0;
if ( !hasData ) {
// Add some initial data
contentArray = [NSMutableArray arrayWithCapacity:100];
for ( NSUInteger i = 0; i < 5; i++ ) {
NSNumber *x = #(1.0 + i * 0.05);
NSNumber *y = #(1.2 * arc4random() / (double)UINT32_MAX + 1.2);
[contentArray addObject:#{ #"x": x,
#"y": y }
];
}
self.content = contentArray;
hasData = YES;
}
// Auto scale the plot space to fit the plot data
// Extend the y range by 10% for neatness
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)self.graph.defaultPlotSpace;
plotSpace.allowsMomentum = YES;
[plotSpace scaleToFitPlots:#[boundLinePlot]];
CPTPlotRange *xRange = plotSpace.xRange;
CPTMutablePlotRange *yRange = [plotSpace.yRange mutableCopy];
[yRange expandRangeByFactor:CPTDecimalFromDouble(1.1)];
plotSpace.yRange = yRange;
// Restrict y range to a global range
plotSpace.globalXRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-1.0) length:CPTDecimalFromDouble(10.0)];
plotSpace.globalYRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-1.0) length:CPTDecimalFromDouble(5.0)];
// set the x and y shift to match the new ranges
CGFloat length = xRange.lengthDouble;
self.xShift = length - 3.0;
length = yRange.lengthDouble;
self.yShift = length - 2.0;
}
-(void)insertData:(uint32 *) buf :(uint32 *) i
{
NSNumber *ni = #(*i);
//NSNumber *nbuf = #(*buf);
[contentArray addObject:#{ #"x": ni,
#"y": ni }
];
self.content = contentArray;
[graph reloadData];
}
#pragma mark -
#pragma mark Plot Data Source Methods
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
if ( [plot isKindOfClass:[CPTBarPlot class]] ) {
return 8;
}
else {
return [self.arrangedObjects count];
}
}
-(id)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
NSNumber *num;
if ( [plot isKindOfClass:[CPTBarPlot class]] ) {
num = #( (index + 1) * (index + 1) );
if ( [plot.identifier isEqual:bindingsPlot] ) {
num = #(num.integerValue - 10);
}
}
else {
NSString *key = (fieldEnum == CPTScatterPlotFieldX ? #"x" : #"y");
num = (self.arrangedObjects)[index][key];
if ( fieldEnum == CPTScatterPlotFieldY ) {
num = #([num doubleValue] + 1.0);
}
}
return num;
}
-(CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)index
{
if ( [(NSString *)plot.identifier isEqualToString : bindingsPlot] ) {
return (id)[NSNull null]; // Don't show any label
}
else if ( [(NSString *)plot.identifier isEqualToString : bindingsPlot] && (index < 4) ) {
return (id)[NSNull null];
}
else if ( index % 4 ) {
return (id)[NSNull null];
}
else {
return nil; // Use default label style
}
}
#pragma mark -
#pragma mark CPTScatterPlot delegate method
-(void)scatterPlot:(CPTScatterPlot *)plot plotSymbolWasSelectedAtRecordIndex:(NSUInteger)index
{
CPTPlotSpaceAnnotation *annotation = self.symbolTextAnnotation;
if ( annotation ) {
[self.graph.plotAreaFrame.plotArea removeAnnotation:annotation];
self.symbolTextAnnotation = nil;
}
// Setup a style for the annotation
CPTMutableTextStyle *hitAnnotationTextStyle = [CPTMutableTextStyle textStyle];
hitAnnotationTextStyle.color = [CPTColor whiteColor];
hitAnnotationTextStyle.fontSize = 16.0f;
hitAnnotationTextStyle.fontName = #"Helvetica-Bold";
// Determine point of symbol in plot coordinates
NSDictionary *dataPoint = (self.arrangedObjects)[index];
NSNumber *x = dataPoint[#"x"];
NSNumber *y = dataPoint[#"y"];
NSArray *anchorPoint = #[x, y];
// Add annotation
// First make a string for the y value
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setMaximumFractionDigits:2];
NSString *yString = [formatter stringFromNumber:y];
// Now add the annotation to the plot area
CPTTextLayer *textLayer = [[CPTTextLayer alloc] initWithText:yString style:hitAnnotationTextStyle];
annotation = [[CPTPlotSpaceAnnotation alloc] initWithPlotSpace:self.graph.defaultPlotSpace anchorPlotPoint:anchorPoint];
annotation.contentLayer = textLayer;
annotation.displacement = CGPointMake(0.0, 20.0);
[self.graph.plotAreaFrame.plotArea addAnnotation:annotation];
self.symbolTextAnnotation = annotation;
}
#pragma mark -
#pragma mark Plot area delegate method
-(void)plotAreaWasSelected:(CPTPlotArea *)plotArea
{
// Remove the annotation
CPTPlotSpaceAnnotation *annotation = self.symbolTextAnnotation;
if ( annotation ) {
[self.graph.plotAreaFrame.plotArea removeAnnotation:annotation];
self.symbolTextAnnotation = nil;
}
}
#pragma mark -
#pragma mark PDF / image export
-(IBAction)exportToPDF:(id)sender
{
NSSavePanel *pdfSavingDialog = [NSSavePanel savePanel];
[pdfSavingDialog setAllowedFileTypes:#[#"pdf"]];
if ( [pdfSavingDialog runModal] == NSOKButton ) {
NSData *dataForPDF = [self.graph dataForPDFRepresentationOfLayer];
[dataForPDF writeToURL:[pdfSavingDialog URL] atomically:NO];
}
}
-(IBAction)exportToPNG:(id)sender
{
NSSavePanel *pngSavingDialog = [NSSavePanel savePanel];
[pngSavingDialog setAllowedFileTypes:#[#"png"]];
if ( [pngSavingDialog runModal] == NSOKButton ) {
NSImage *image = [self.graph imageOfLayer];
NSData *tiffData = [image TIFFRepresentation];
NSBitmapImageRep *tiffRep = [NSBitmapImageRep imageRepWithData:tiffData];
NSData *pngData = [tiffRep representationUsingType:NSPNGFileType properties:nil];
[pngData writeToURL:[pngSavingDialog URL] atomically:NO];
}
}
#pragma mark -
#pragma mark Printing
-(IBAction)printDocument:(id)sender
{
NSPrintInfo *printInfo = [NSPrintInfo sharedPrintInfo];
NSRect printRect = NSZeroRect;
printRect.size.width = (printInfo.paperSize.width - printInfo.leftMargin - printInfo.rightMargin) * printInfo.scalingFactor;
printRect.size.height = (printInfo.paperSize.height - printInfo.topMargin - printInfo.bottomMargin) * printInfo.scalingFactor;
self.hostView.printRect = printRect;
NSPrintOperation *printOperation = [NSPrintOperation printOperationWithView:self.hostView printInfo:printInfo];
[printOperation runOperationModalForWindow:self.hostView.window
delegate:self
didRunSelector:#selector(printOperationDidRun:success:contextInfo:)
contextInfo:NULL];
}
-(void)printOperationDidRun:(NSPrintOperation *)printOperation success:(BOOL)success contextInfo:(void *)contextInfo
{
// print delegate
}
Core Plot expects the data values to be NSNumber instances, not plain integers. You can use NSDecimalNumber (a subclass of NSNumber) if you need to preserve full decimal precision.
Since you're using data bound to an NSArrayController, -reloadData and related methods will have no effect. Those are only used when providing data through a datasource. That's the only method available on iOS which is why much of the sample code and demos on the web use it.
Once an NSArrayController is initialized, you should use its methods to add or remove data rather than updating the content array directly. The CPTTestAPP demo uses -insertObject:atArrangedObjectIndex: and -removeObjectAtArrangedObjectIndex: to do this.
I'm doing an application that requires core plot for drawing charts, I'm new to this library and I am finding it pretty hard to find good documentation or examples. I'm running into a problem where the line for the graph is not being display despite the fact that the data source method is getting called and returning the right number at the right index. Also the x Axis is being displayed wrong (Check the image below(1.0)). The Y axis is set correctly and the increment is also correct. I've been playing around trying to figure out what it's wrong but I spent too much time already so I was hoping to find some one here that could help or point me at the right direction. This is my implementation file :
-(void)initPlot {
[self generateData];
[self configureHost];
[self configureGraph];
[self configurePlots];
[self configureAxes];
}
- (void)generateData{
//Array containing all the dates that will be displayed on the X axis
dates = [NSArray arrayWithObjects:#"Apr 25", #"Apr 26", #"Apr 29",#"Apr 30", #"May 1", nil];
//Dictionary containing the name of the single set and its associated color
sets = [NSDictionary dictionaryWithObjectsAndKeys:[UIColor redColor], #"Plot 1",nil];
_dataY = [[NSMutableArray alloc] init];
[_dataY insertObject:[NSNumber numberWithFloat:618.0] atIndex:0];
[_dataY insertObject:[NSNumber numberWithFloat:613.0] atIndex:0];
[_dataY insertObject:[NSNumber numberWithFloat:613.0] atIndex:0];
[_dataY insertObject:[NSNumber numberWithFloat:614.0] atIndex:0];
[_dataY insertObject:[NSNumber numberWithFloat:604.0] atIndex:0];
_dataForPlot = [[NSMutableArray alloc] init];
for(int i = 0; i < dates.count; i++){
NSString *date = [dates objectAtIndex:i];
NSNumber *price = [_dataY objectAtIndex:i];
NSMutableDictionary *point1 = [[[NSMutableDictionary alloc] initWithObjectsAndKeys:date, #"x", price, #"y", nil] autorelease];
[_dataForPlot addObject:point1];
}
NSLog(#"Data %#",_dataForPlot);
}
-(void)configureHost {
_hostView.allowPinchScaling = NO;
}
-(void)configureGraph {
graph = [[CPTXYGraph alloc] initWithFrame:CGRectZero];
[graph applyTheme:[CPTTheme themeNamed:kCPTPlainBlackTheme]];
_hostView.hostedGraph = graph;
graph.plotAreaFrame.masksToBorder = NO;
// Configure the Graph Padding
graph.paddingLeft = 0.0f;
graph.paddingTop = 0.0f;
graph.paddingRight = 0.0f;
graph.paddingBottom = 0.0f;
CPTMutableLineStyle *borderLineStyle = [CPTMutableLineStyle lineStyle];
borderLineStyle.lineColor = [CPTColor whiteColor];
borderLineStyle.lineWidth = 2.0f;
graph.plotAreaFrame.borderLineStyle = borderLineStyle;
graph.plotAreaFrame.paddingTop = 10.0;
graph.plotAreaFrame.paddingRight = 10.0;
graph.plotAreaFrame.paddingBottom = 40.0;
graph.plotAreaFrame.paddingLeft = 70.0;
// Set graph title
graph.title = #"Test";
// Create and set text style
CPTMutableTextStyle *titleStyle = [CPTMutableTextStyle textStyle];
titleStyle.color = [CPTColor whiteColor];
titleStyle.fontName = #"Helvetica-Bold";
titleStyle.fontSize = 16.0f;
graph.titleTextStyle = titleStyle;
graph.titlePlotAreaFrameAnchor = CPTRectAnchorTop;
graph.titleDisplacement = CGPointMake(0.0f, 10.0f);
graph.plotAreaFrame.borderLineStyle = nil;
}
- (void)configurePlots{
CPTColor *aColor = [CPTColor redColor];
CPTMutableLineStyle *barLineStyle = [[[CPTMutableLineStyle alloc] init] autorelease];
barLineStyle.lineWidth = 1.0;
barLineStyle.lineColor = [CPTColor whiteColor];
CPTMutableTextStyle *whiteTextStyle = [CPTMutableTextStyle textStyle];
whiteTextStyle.color = [CPTColor whiteColor];
// Enable user interactions for plot space
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graph.defaultPlotSpace;
plotSpace.allowsUserInteraction = YES;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0) length:CPTDecimalFromFloat(5.0)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat([self lowerValue]) length:CPTDecimalFromFloat([self higherValue])];
dataSourceLinePlot = [[[CPTScatterPlot alloc] init] autorelease];
dataSourceLinePlot.identifier = #"Plot 1";
dataSourceLinePlot.dataSource = self;
[graph addPlot:dataSourceLinePlot];
CPTGradient *areaGradient = [CPTGradient gradientWithBeginningColor :[CPTColor greenColor]
endingColor :[CPTColor blackColor]];
areaGradient.angle = -90.0f ;
CPTFill *areaGradientFill = [ CPTFill fillWithGradient :areaGradient];
dataSourceLinePlot.areaFill = areaGradientFill;
dataSourceLinePlot.areaBaseValue = CPTDecimalFromString (#"0.0");
dataSourceLinePlot.interpolation = CPTScatterPlotInterpolationLinear;
// Set up plot space
[plotSpace scaleToFitPlots:[NSArray arrayWithObjects:dataSourceLinePlot, nil]];
CPTMutablePlotRange *xRange = [plotSpace.xRange mutableCopy];
[xRange expandRangeByFactor:CPTDecimalFromCGFloat(1.1f)];
plotSpace.xRange = xRange;
CPTMutablePlotRange *yRange = [plotSpace.yRange mutableCopy];
[yRange expandRangeByFactor:CPTDecimalFromCGFloat(1.4f)];
plotSpace.yRange = yRange;
// Create styles and symbols
CPTMutableLineStyle *aLineStyle = [[dataSourceLinePlot.dataLineStyle mutableCopy] autorelease];
aLineStyle.lineWidth = 1.0;
aLineStyle.lineColor = aColor;
dataSourceLinePlot.dataLineStyle = aLineStyle;
//Add legend
CPTLegend *theLegend = [CPTLegend legendWithGraph:graph];
theLegend.numberOfRows = sets.count;
theLegend.fill = [CPTFill fillWithColor:[CPTColor colorWithGenericGray:0.15]];
theLegend.borderLineStyle = barLineStyle;
theLegend.cornerRadius = 10.0;
theLegend.swatchSize = CGSizeMake(15.0, 15.0);
whiteTextStyle.fontSize = 13.0;
theLegend.textStyle = whiteTextStyle;
theLegend.rowMargin = 5.0;
theLegend.paddingLeft = 10.0;
theLegend.paddingTop = 10.0;
theLegend.paddingRight = 10.0;
theLegend.paddingBottom = 10.0;
graph.legend = theLegend;
graph.legendAnchor = CPTRectAnchorTopLeft;
graph.legendDisplacement = CGPointMake(80.0, -10.0);
}
- (void)configureAxes{
CPTMutableTextStyle *axisTextStyle = [[CPTMutableTextStyle alloc] init];
axisTextStyle.color = [CPTColor whiteColor];
axisTextStyle.fontName = #"Helvetica-Bold";
axisTextStyle.fontSize = 11.0f;
// Grid line styles
CPTMutableLineStyle *majorGridLineStyle = [CPTMutableLineStyle lineStyle];
majorGridLineStyle.lineWidth = 0.75;
majorGridLineStyle.lineColor = [[CPTColor whiteColor] colorWithAlphaComponent:0.1];
CPTMutableLineStyle *minorGridLineStyle = [CPTMutableLineStyle lineStyle];
minorGridLineStyle.lineWidth = 0.25;
minorGridLineStyle.lineColor = [[CPTColor whiteColor] colorWithAlphaComponent:0.1];
// Line Style
CPTMutableLineStyle *lineStyle = [CPTMutableLineStyle lineStyle];
lineStyle.lineColor = [CPTColor whiteColor];
lineStyle.lineWidth = 2.0f;
CPTMutableLineStyle *axisLineStyle = [CPTMutableLineStyle lineStyle];
axisLineStyle.lineWidth = 2.0f;
axisLineStyle.lineColor = [CPTColor whiteColor];
//Axises
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
//Y axis
CPTXYAxis *y = axisSet.yAxis;
y.title = #"Price";
y.titleOffset = 50.0f;
y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
y.majorGridLineStyle = majorGridLineStyle;
y.minorGridLineStyle = minorGridLineStyle;
y.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];
y. majorIntervalLength = CPTDecimalFromString(#"5");
y.minorTicksPerInterval = 4;
y.orthogonalCoordinateDecimal = CPTDecimalFromString(#"0");
y.minorTickLineStyle = nil;
y.labelOffset = 2.0f;
// Configure x-axis
CPTXYAxis *x = axisSet.xAxis;
x. majorIntervalLength = CPTDecimalFromString (#"5");
x.orthogonalCoordinateDecimal = CPTDecimalFromInt(0);
x.majorIntervalLength = CPTDecimalFromInt(5);
x.minorTicksPerInterval = 0;
x.labelingPolicy = CPTAxisLabelingPolicyNone;
x.majorGridLineStyle = majorGridLineStyle;
x.axisConstraints = [CPTConstraints constraintWithLowerOffset:0.0];
NSMutableArray *customLabels = [NSMutableArray arrayWithCapacity:[_dataForPlot count]];
static CPTMutableTextStyle *labelTextStyle = nil;
labelTextStyle = [[CPTMutableTextStyle alloc] init];
labelTextStyle.color = [CPTColor whiteColor];
labelTextStyle.fontSize = 10.0f;
int index = 0;
for(NSString *date in dates){
CPTAxisLabel *newLabel = [[CPTAxisLabel alloc] initWithText:date textStyle:labelTextStyle];
newLabel.tickLocation = CPTDecimalFromInt(index);
newLabel.offset = x.labelOffset + x.majorTickLength + 5;
newLabel.rotation = M_PI / 4;
[customLabels addObject:newLabel];
[newLabel release];
index++;
}
x.axisLabels = [NSSet setWithArray:customLabels];
}
- (float)higherValue{
NSNumber* max = [_dataY valueForKeyPath:#"#max.self"];
return [max floatValue];
}
- (float)lowerValue{
NSNumber* min = [_dataY valueForKeyPath:#"#min.self"];
return [min floatValue];
}
The Data Source Methods :
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot {
return dates.count;
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index {
NSString *key = (fieldEnum == CPTScatterPlotFieldX ? #"x" : #"y");
NSNumber *num = 0;
//if ( [(NSString *)plot.identifier isEqualToString:#"Plot 1"] ) {
num = [[_dataForPlot objectAtIndex:index] valueForKey:key];
if ( fieldEnum == CPTScatterPlotFieldX ) {
num = 0;
}
//}
CABasicAnimation *fadeInAnimation = [CABasicAnimation animationWithKeyPath:#"opacity"];
fadeInAnimation.duration = 1.0f;
fadeInAnimation.removedOnCompletion = NO;
fadeInAnimation.fillMode = kCAFillModeForwards;
fadeInAnimation.toValue = [NSNumber numberWithFloat:2.0];
[dataSourceLinePlot addAnimation:fadeInAnimation forKey:#"animateOpacity"];
NSLog(#"NUM : %# for key : %# at index : %i",num,key,index);
return num;
}
This is the image :
The x-axis is displayed exactly as you told it. It ranges between -0.25 and 5.25 (0 to 5 expanded by 10%) with five labels at 0, 1, 2, 3, and 4.
The datasource returns nil (0) for the CPTScatterPlotFieldX field for every point. This tells the plot to ignore that point. Based on the plot place range you've set up, you should return an NSNumber containing the index for that field.
I'm having a strange issue with custom UICollectionViewFlowLayout, my cells contain an imageView, I apply a zoom effect to my cells... however I think that I'm doing something wrong with the Zoom Effect, it's strange, because my cells get scaled correctly, the problem is that the imageView for some cells is not.
Here's the relevant code (I think) for this issue, (note that If I remove the method: - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect or the CATransform3DMakeScale, the problem doesn't seem to appear.)
///// UICollectionViewController.m
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
HICollectionViewCell *cell = (HICollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:COLLECTION_VIEW_CELL_ID forIndexPath:indexPath];
[self customizeCell:cell atIndexPath:indexPath];
return cell;
}
#pragma mark - CollectionView FlowDelegate
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(200.0f, 200.0f);
}
#pragma mark - "Private" Methods
- (void)customizeCell:(HICollectionViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
UIImageView *view = (UIImageView *)[cell.contentView viewWithTag:kCollectionViewCellSubViewTag_imgView];
if (!view.image) {
view.image = [UIImage imageNamed:#"placeholder.png"];
}
}
The Custom Layout Inherits from UICollectionViewFlowLayout
/////// CustomLayout.m
static const CGFloat ACTIVE_DISTANCE = 200.0f;
static const CGFloat ZOOM_FACTOR = 0.3f;
- (id)init
{
if(self = [super init]) {
self.itemSize = CGSizeMake(ITEM_SIZE, ITEM_SIZE);
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.sectionInset = UIEdgeInsetsMake(200.0f, 0.0f, 200.0f, 0.0f);
self.minimumLineSpacing = 50.0f;
}
return self;
}
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *attributes = [super layoutAttributesForElementsInRect:rect];
CGRect visibleRect;
visibleRect.origin = self.collectionView.contentOffset;
visibleRect.size = self.collectionView.bounds.size;
for (UICollectionViewLayoutAttributes *attribute in attributes) {
if (CGRectIntersectsRect(attribute.frame, rect)) {
CGFloat distance = CGRectGetMidX(visibleRect) - attribute.center.x;
CGFloat normalizedDistance = distance / ACTIVE_DISTANCE;
// Apply a zoom factor to cells within ACTIVE_DISTANCE
if (ABS(distance) < ACTIVE_DISTANCE) {
CGFloat zoom = 1.0f + ZOOM_FACTOR * (1.0f - ABS(normalizedDistance));
attribute.transform3D = CATransform3DMakeScale(zoom, zoom, 1.0);
attribute.zIndex = round(zoom);
}
}
}
return attributes;
}
As the FlowLayout appears everything looks fine.
Then I start to scroll and I notice that the background layer of the cells to the right starts to show off (backgroundColor is orange)
As you can see, after two cells, the third one ( that starts to appear, looks OK again ).
Maybe it's an issue with the cell queue and dequeue (and the imageView being re-used or something?).
Can someone help me out with why this error showed up after I upgraded to the newest version of xcode? The app was working fine prior to this, but this syntax error prevents compiling now. I am getting the error at
#pragma mark -#property (nonatomic, k Constants,
and also I get a missing #end error.
Sorry for posting the entire page, but I wanted to make sure I provided enough to get assistance.
#import "MBProgressHUD.h"
#interface MBProgressHUD ()
(void)hideUsingAnimation:(BOOL)animated;
(void)showUsingAnimation:(BOOL)animated;
(void)fillRoundedRect:(CGRect)rect inContext:(CGContextRef)context;
(void)done;
(void)updateLabelText:(NSString *)newText;
(void)updateDetailsLabelText:(NSString *)newText;
(void)updateProgress;
(void)updateIndicators;
(void)handleGraceTimer:(NSTimer *)theTimer;
(void)handleMinShowTimer:(NSTimer *)theTimer;
#property (retain) UIView *indicator;
#property (assign) float width;
#property (assign) float height;
#property (retain) NSTimer *graceTimer;
#property (retain) NSTimer *minShowTimer;
#property (retain) NSDate *showStarted;
#end
#implementation MBProgressHUD
#pragma mark -
#pragma mark Accessors
#synthesize mode;
#synthesize delegate;
#synthesize labelText;
#synthesize detailsLabelText;
#synthesize opacity;
#synthesize labelFont;
#synthesize detailsLabelFont;
#synthesize progress;
#synthesize indicator;
#synthesize width;
#synthesize height;
#synthesize xOffset;
#synthesize yOffset;
#synthesize graceTime;
#synthesize minShowTime;
#synthesize graceTimer;
#synthesize minShowTimer;
#synthesize taskInProgress;
#synthesize showStarted;
(void)setMode:(MBProgressHUDMode)newMode {
if (mode && (mode == newMode)) {
return;
}
mode = newMode;
[self performSelectorOnMainThread:#selector(updateIndicators) withObject:nil waitUntilDone:NO];
[self performSelectorOnMainThread:#selector(setNeedsLayout) withObject:nil waitUntilDone:NO];
[self performSelectorOnMainThread:#selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
}
(void)setLabelText:(NSString *)newText {
[self performSelectorOnMainThread:#selector(updateLabelText:) withObject:newText waitUntilDone:NO];
[self performSelectorOnMainThread:#selector(setNeedsLayout) withObject:nil waitUntilDone:NO];
[self performSelectorOnMainThread:#selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
}
(void)setDetailsLabelText:(NSString *)newText {
[self performSelectorOnMainThread:#selector(updateDetailsLabelText:) withObject:newText waitUntilDone:NO];
[self performSelectorOnMainThread:#selector(setNeedsLayout) withObject:nil waitUntilDone:NO];
[self performSelectorOnMainThread:#selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
}
(void)setProgress:(float)newProgress {
progress = newProgress;
if (mode == MBProgressHUDModeDeterminate) {
[self performSelectorOnMainThread:#selector(updateProgress) withObject:nil waitUntilDone:NO];
[self performSelectorOnMainThread:#selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
}
}
#pragma mark -
#pragma mark Accessor helpers
(void)updateLabelText:(NSString *)newText {
if (labelText != newText) {
[labelText release];
labelText = [newText copy];
}
}
(void)updateDetailsLabelText:(NSString *)newText {
if (detailsLabelText != newText) {
[detailsLabelText release];
detailsLabelText = [newText copy];
}
}
(void)updateProgress {
[(MBRoundProgressView *)indicator setProgress:progress];
}
(void)updateIndicators {
if (indicator) {
[indicator removeFromSuperview];
}
self.indicator = nil;
if (mode == MBProgressHUDModeDeterminate) {
self.indicator = [[MBRoundProgressView alloc] initWithDefaultSize];
}
else {
self.indicator = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[(UIActivityIndicatorView *)indicator startAnimating];
}
[self addSubview:indicator];
}
**#pragma mark -
#property (nonatomic, k Constants**
#define MARGIN 20.0
#define PADDING 4.0
#define LABELFONTSIZE 22.0
#define LABELDETAILSFONTSIZE 16.0
#define PI 3.14159265358979323846
#pragma mark -
#pragma mark Lifecycle methods
(id)initWithWindow:(UIWindow *)window {
#property (nonatomic, nonatomic, nonatomic, [self initWithView:window];
}
(id)initWithView:(UIView *)view {
initializer above)
if (!view) {
#property (nonatomic, ion raise:#"MBProgressHUDViewIsNillException"
format:#"The view used in the MBProgressHUD initializer is nil."];
}
return [self initWithFrame:view.bounds];
}
(id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.mode = MBProgressHUDModeIndeterminate;
self.labelText = nil;
self.detailsLabelText = nil;
self.opacity = 0.9;
self.labelFont = [UIFont boldSystemFontOfSize:LABELFONTSIZE];
self.detailsLabelFont = [UIFont boldSystemFontOfSize:LABELDETAILSFONTSIZE];
self.xOffset = 0.0;
self.yOffset = 0.0;
self.graceTime = 0.0;
self.minShowTime = 0.0;
self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
self.opaque = NO;
self.backgroundColor = [UIColor clearColor];
self.alpha = 0.0;
label = [[UILabel alloc] initWithFrame:self.bounds];
detailsLabel = [[UILabel alloc] initWithFrame:self.bounds];
taskInProgress = NO;
}
return self;
}
(void)dealloc {
[indicator release];
[label release];
[detailsLabel release];
[labelText release];
[detailsLabelText release];
[graceTimer release];
[minShowTimer release];
[showStarted release];
[super dealloc];
}
#pragma mark -
#pragma mark Layout
(void)layoutSubviews {
CGRect frame = self.bounds;
#property (nonatomic, indFrame = indicator.bounds;
self.width = indFrame.size.width + 2 * MARGIN;
self.height = indFrame.size.height + 2 * MARGIN;
indFrame.origin.x = floor((frame.size.width - indFrame.size.width) / 2) + self.xOffset;
indFrame.origin.y = floor((frame.size.height - indFrame.size.height) / 2) + self.yOffset;
indicator.frame = indFrame;
if (nil != self.labelText) {
CGSize dims = [self.labelText sizeWithFont:self.labelFont];
clip the label width
float lHeight = dims.height;
float lWidth;
if (dims.width <= (frame.size.width - 2 * MARGIN)) {
lWidth = dims.width;
}
else {
lWidth = frame.size.width - 4 * MARGIN;
}
label.font = self.labelFont;
label.adjustsFontSizeToFitWidth = NO;
label.textAlignment = UITextAlignmentCenter;
label.opaque = NO;
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor whiteColor];
label.text = self.labelText;
if (self.width < (lWidth + 2 * MARGIN)) {
self.width = lWidth + 2 * MARGIN;
}
self.height = self.height + lHeight + PADDING;
indFrame.origin.y -= (floor(lHeight / 2 + PADDING / 2));
indicator.frame = indFrame;
// Set the label position and dimensions
CGRect lFrame = CGRectMake(floor((frame.size.width - lWidth) / 2) + xOffset,
floor(indFrame.origin.y + indFrame.size.height + PADDING),
lWidth, lHeight);
label.frame = lFrame;
[self addSubview:label];
// Add details label delatils text was set
if (nil != self.detailsLabelText) {
// Get size of label text
dims = [self.detailsLabelText sizeWithFont:self.detailsLabelFont];
// Compute label dimensions based on font metrics if size is larger than max then clip the label width
lHeight = dims.height;
if (dims.width <= (frame.size.width - 2 * MARGIN)) {
lWidth = dims.width;
}
else {
lWidth = frame.size.width - 4 * MARGIN;
}
// Set label properties
detailsLabel.font = self.detailsLabelFont;
detailsLabel.adjustsFontSizeToFitWidth = NO;
detailsLabel.textAlignment = UITextAlignmentCenter;
detailsLabel.opaque = NO;
detailsLabel.backgroundColor = [UIColor clearColor];
detailsLabel.textColor = [UIColor whiteColor];
detailsLabel.text = self.detailsLabelText;
// Update HUD size
if (self.width < lWidth) {
self.width = lWidth + 2 * MARGIN;
}
self.height = self.height + lHeight + PADDING;
// Move indicator to make room for the new label
indFrame.origin.y -= (floor(lHeight / 2 + PADDING / 2));
indicator.frame = indFrame;
// Move first label to make room for the new label
lFrame.origin.y -= (floor(lHeight / 2 + PADDING / 2));
label.frame = lFrame;
// Set label position and dimensions
CGRect lFrameD = CGRectMake(floor((frame.size.width - lWidth) / 2) + xOffset,
lFrame.origin.y + lFrame.size.height + PADDING, lWidth, lHeight);
detailsLabel.frame = lFrameD;
[self addSubview:detailsLabel];
}
}
}
#pragma mark -
#pragma mark Showing and execution
- (void)show:(BOOL)animated {
useAnimation = animated;
// If the grace time is set postpone the HUD display
if (self.graceTime > 0.0) {
self.graceTimer = [NSTimer scheduledTimerWithTimeInterval:self.graceTime
target:self
selector:#selector(handleGraceTimer:)
userInfo:nil
repeats:NO];
}
// ... otherwise show the HUD imediately
else {
[self setNeedsDisplay];
[self showUsingAnimation:useAnimation];
}
}
- (void)hide:(BOOL)animated {
useAnimation = animated;
// If the minShow time is set, calculate how long the hud was shown,
// and pospone the hiding operation if necessary
if (self.minShowTime > 0.0 && showStarted) {
NSTimeInterval interv = [[NSDate date] timeIntervalSinceDate:showStarted];
if (interv < self.minShowTime) {
self.minShowTimer = [NSTimer scheduledTimerWithTimeInterval:(self.minShowTime - interv)
target:self
selector:#selector(handleMinShowTimer:)
userInfo:nil
repeats:NO];
return;
}
}
// ... otherwise hide the HUD immediately
[self hideUsingAnimation:useAnimation];
}
- (void)handleGraceTimer:(NSTimer *)theTimer {
// Show the HUD only if the task is still running
if (taskInProgress) {
[self setNeedsDisplay];
[self showUsingAnimation:useAnimation];
}
}
- (void)handleMinShowTimer:(NSTimer *)theTimer {
[self hideUsingAnimation:useAnimation];
}
- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated {
methodForExecution = method;
targetForExecution = [target retain];
objectForExecution = [object retain];
// Launch execution in new thread
taskInProgress = YES;
[NSThread detachNewThreadSelector:#selector(launchExecution) toTarget:self withObject:nil];
// Show HUD view
[self show:animated];
}
- (void)launchExecution {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Start executing the requested task
[targetForExecution performSelector:methodForExecution withObject:objectForExecution];
// Task completed, update view in main thread (note: view operations should
// be done only in the main thread)
[self performSelectorOnMainThread:#selector(cleanUp) withObject:nil waitUntilDone:NO];
[pool release];
}
- (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void*)context {
[self done];
}
- (void)done {
isFinished = YES;
// If delegate was set make the callback
self.alpha = 0.0;
if(delegate != nil && [delegate conformsToProtocol:#protocol(MBProgressHUDDelegate)]) {
if([delegate respondsToSelector:#selector(hudWasHidden)]) {
[delegate performSelector:#selector(hudWasHidden)];
}
}
}
- (void)cleanUp {
taskInProgress = NO;
self.indicator = nil;
[targetForExecution release];
[objectForExecution release];
[self hide:useAnimation];
}
#pragma mark -
#pragma mark Fade in and Fade out
- (void)showUsingAnimation:(BOOL)animated {
self.showStarted = [NSDate date];
// Fade in
if (animated) {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.40];
self.alpha = 1.0;
[UIView commitAnimations];
}
else {
self.alpha = 1.0;
}
}
- (void)hideUsingAnimation:(BOOL)animated {
// Fade out
if (animated) {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.40];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationFinished: finished: context:)];
// 0.02 prevents the hud from passing through touches during the animation the hud will get completely hidden
// in the done method
self.alpha = 0.02;
[UIView commitAnimations];
}
else {
self.alpha = 0.0;
[self done];
}
}
#pragma mark BG Drawing
- (void)drawRect:(CGRect)rect {
// Center HUD
CGRect allRect = self.bounds;
// Draw rounded HUD bacgroud rect
CGRect boxRect = CGRectMake(((allRect.size.width - self.width) / 2) + self.xOffset,
((allRect.size.height - self.height) / 2) + self.yOffset, self.width, self.height);
CGContextRef ctxt = UIGraphicsGetCurrentContext();
[self fillRoundedRect:boxRect inContext:ctxt];
}
- (void)fillRoundedRect:(CGRect)rect inContext:(CGContextRef)context {
float radius = 10.0f;
CGContextBeginPath(context);
CGContextSetGrayFillColor(context, 0.0, self.opacity);
CGContextMoveToPoint(context, CGRectGetMinX(rect) + radius, CGRectGetMinY(rect));
CGContextAddArc(context, CGRectGetMaxX(rect) - radius, CGRectGetMinY(rect) + radius, radius, 3 * M_PI / 2, 0, 0);
CGContextAddArc(context, CGRectGetMaxX(rect) - radius, CGRectGetMaxY(rect) - radius, radius, 0, M_PI / 2, 0);
CGContextAddArc(context, CGRectGetMinX(rect) + radius, CGRectGetMaxY(rect) - radius, radius, M_PI / 2, M_PI, 0);
CGContextAddArc(context, CGRectGetMinX(rect) + radius, CGRectGetMinY(rect) + radius, radius, M_PI, 3 * M_PI / 2, 0);
CGContextClosePath(context);
CGContextFillPath(context);
}
#end
#implementation MBRoundProgressView
- (id)initWithDefaultSize {
return [super initWithFrame:CGRectMake(0.0f, 0.0f, 37.0f, 37.0f)];
}
- (void)drawRect:(CGRect)rect {
CGRect allRect = self.bounds;
CGRect circleRect = CGRectMake(allRect.origin.x + 2, allRect.origin.y + 2, allRect.size.width - 4,
allRect.size.height - 4);
CGContextRef context = UIGraphicsGetCurrentContext();
// Draw background
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); // white
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.1); // translucent white
CGContextSetLineWidth(context, 2.0);
CGContextFillEllipseInRect(context, circleRect);
CGContextStrokeEllipseInRect(context, circleRect);
// Draw progress
float x = (allRect.size.width / 2);
float y = (allRect.size.height / 2);
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0); // white
CGContextMoveToPoint(context, x, y);
CGContextAddArc(context, x, y, (allRect.size.width - 4) / 2, -(PI / 2), (self.progress * 2 * PI) - PI / 2, 0);
CGContextClosePath(context);
CGContextFillPath(context);
}
#end
The line throwing the error makes no sense.
#pragma mark -
#property (nonatomic, k Constants
the #pragma mark - puts a line in the drop down list but what is the next line supposed to do?
if you are declaring a property, then you haven't closed the bracket after nonatomic, but when what is k Constants supposed to be. Are you sure you didn't change the file?
I would like to use auto layout to position a UITextField next to cell.textLabel when a UITableView goes into edit mode. The code that I have works correctly but I get a message in the log that says some existing constraints had to be broken.
UILabel *label = cell.textLabel;
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(0.0, 0.0, 400.0, 22.0)];
textField.placeholder = cell.textLabel.text;
textField.translatesAutoresizingMaskIntoConstraints = NO;
textField.text = text;
[cell.contentView addSubview:textField];
[cell addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[label]-[textField]-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(label,textField)]];
[cell addConstraint:[NSLayoutConstraint constraintWithItem:textField attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:label attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0]];
Log message is:
(
"<NSAutoresizingMaskLayoutConstraint:0x1066abc0 h=--& v=--& H:[UITableViewCellContentView:0x9a7d070(934)]>",
"<NSAutoresizingMaskLayoutConstraint:0x10660a90 h=--& v=--& H:[UILabel:0x9a93ef0(914)]>",
"<NSLayoutConstraint:0x1065ea60 H:[UITextField:0x1065c660]-(NSSpace(20))-| (Names: '|':UITableViewCellContentView:0x9a7d070 )>",
"<NSAutoresizingMaskLayoutConstraint:0x10660a50 h=--& v=--& UILabel:0x9a93ef0.midX == + 467>",
"<NSLayoutConstraint:0x10669280 H:[UILabel:0x9a93ef0]-(NSSpace(8))-[UITextField:0x1065c660]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x10669280 H:[UILabel:0x9a93ef0]-(NSSpace(8))-[UITextField:0x1065c660]>
I think that this is caused by conflicting restraints with the cell.textLabel width. So my question is if there is another way to have a textfield in a standard table view cell that stretches from the textLabel width to the end of the cell without breaking default constraints. I feel like I'm close but I can't quite get there. I've searched Google over for three weeks but can't quite get my head around this. I've also watched WWDC videos on auto layout (perhaps I'm just an idiot). Thanks for your help.
Instead of trying to manipulate Apple's standard cell, I took the plunge and wrote my own UITableViewCell subclass that mimics UITableViewCellStyleValue1. When the tableview goes into edit mode, in the simplest terms I hide the value label and display the textfield. For those who might be struggling with the same thing, I'm posting some code to help you get started:
#interface NXAlphaNumericTextFieldCell : UITableViewCell<UITextFieldDelegate,NumberKeyboardDelegate>
#property (strong, nonatomic) UITextField *inputTextField;
#property (strong, nonatomic) UILabel *titleLabel;
#property (strong, nonatomic) UILabel *valueLabel;
#property (strong, nonatomic) NSArray *xTitleLabelConstraints;
#property (strong, nonatomic) NSArray *xTextFieldConstraints;
#property (strong, nonatomic) NSArray *xValueLabelConstraints;
#end
And a few methods in the implementation:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 44.0f)];
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.titleLabel.font = [UIFont boldSystemFontOfSize:16.0f];
self.titleLabel.backgroundColor = [UIColor clearColor];
self.valueLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 44.0f)];
self.valueLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.valueLabel.textColor = [UIColor colorWithRed:81.0/255.0 green:102.0/255.0 blue:145.0/255.0 alpha:1.0];
self.valueLabel.backgroundColor = [UIColor clearColor];
self.inputTextField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 44.0f)];
self.inputTextField.translatesAutoresizingMaskIntoConstraints = NO;
self.inputTextField.autocapitalizationType = UITextAutocapitalizationTypeWords;
self.inputTextField.autocorrectionType = UITextAutocorrectionTypeYes;
self.inputTextField.clearButtonMode = UITextFieldViewModeAlways;
self.inputTextField.delegate = self;
[self.contentView addSubview:self.valueLabel];
[self.contentView addSubview:self.titleLabel];
[self.contentView addSubview:self.inputTextField];
UILabel *textLabel = self.titleLabel;
NSDictionary *labelTextFieldViewsDictionary = NSDictionaryOfVariableBindings(textLabel);
self.xTitleLabelConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"|-[textLabel]"
options:0
metrics:nil
views:labelTextFieldViewsDictionary];
UITextField *textfield = self.inputTextField;
labelTextFieldViewsDictionary = NSDictionaryOfVariableBindings(textLabel, textfield);
self.xTextFieldConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"|-[textLabel]-50-[textfield]-|"
options:0
metrics:nil
views:labelTextFieldViewsDictionary];
UILabel *valueLabel = self.valueLabel;
labelTextFieldViewsDictionary = NSDictionaryOfVariableBindings(valueLabel);
self.xValueLabelConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:[valueLabel]-|"
options:0
metrics:nil
views:labelTextFieldViewsDictionary];
[self setNeedsUpdateConstraints];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
if (self.isEditing) {
[self.inputTextField becomeFirstResponder];
}
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
[self addConstraints:self.xTitleLabelConstraints];
if (editing) {
if (self.inputType == kCellInputTypeAlphaNumeric) {
self.inputTextField.keyboardType = UIKeyboardTypeAlphabet;
} else if (self.inputType == kCellInputTypeEmail) {
self.inputTextField.keyboardType = UIKeyboardTypeEmailAddress;
} else if (self.inputType == kCellInputTypePhoneNumber) {
self.inputTextField.keyboardType = UIKeyboardTypeNamePhonePad;
} else {
if (!self.numberKeyboard) {
self.numberKeyboard = [[NumberKeyboard alloc] initWithNibName:#"NumberKeyboard" bundle:nil];
self.numberKeyboard.textField = self.inputTextField;
self.numberKeyboard.showsPeriod = YES;
self.numberKeyboard.delegate = self;
}
self.inputTextField.inputView = self.numberKeyboard.view;
}
self.inputTextField.text = self.valueLabel.text;
self.inputTextField.placeholder = self.titleLabel.text;
self.valueLabel.hidden = YES;
self.inputTextField.hidden = NO;
[self removeConstraints:self.xValueLabelConstraints];
[self addConstraints:self.xTextFieldConstraints];
} else {
[self.inputTextField resignFirstResponder];
self.inputTextField.hidden = YES;
self.valueLabel.hidden = NO;
[self removeConstraints:self.xTextFieldConstraints];
[self addConstraints:self.xValueLabelConstraints];
}
}
- (void)updateConstraints
{
[super updateConstraints];
if (self.editing) {
[self removeConstraints:self.xValueLabelConstraints];
[self addConstraints:self.xTextFieldConstraints];
} else {
[self removeConstraints:self.xTextFieldConstraints];
[self addConstraints:self.xValueLabelConstraints];
}
}