I have an array called spriteArray:
#property (retain) NSMutableArray *spriteArray;
#synthesize spriteArray = spriteArray_;
And I have a sprite:
#property (nonatomic, assign) CCSprite *sprite;
#synthesize sprite = sprite_;
I create a certain number of sprites depending on the value of spriteNumber (an integer):
for (int i = 0; i < spriteNumber; i++) {
if ([spritetype_ isEqualToString:#"typeOne"]) {
self.sprite = [[typeOne alloc] initTypeOne];
self.sprite.position = randomPoint;
[self.spriteArray addObject:self.sprite];
[self addChild:self.sprite];
}}
The sprites initialise successfully, and appear on the screen as they should. However, when I try to use them for collision detection, only one of them works:
if (CGRectIntersectsRect(self.sprite.boundingBox, self.swat.boundingBox)) {
//swat is another sprite
NSLog(#"detected");
}
What I wanted is to 'index' each of the sprites as they are being created, so that the collision detection works.
SAMPLE CODE: http://pastebin.com/swNUwB6U
Use the tag property for the sprite.
for (int i = 0; i < spriteNumber; i++) {
if ([spritetype_ isEqualToString:#"typeOne"]) {
typeOne *typeOneSprite = [[typeOne alloc] initTypeOne];
typeOneSprite.position = randomPoint;
// USE TAG!
typeOneSprite.tag = i;
[self.spriteArray addObject:typeOneSprite];
[self addChild:typeOneSprite];
// Don't forget to release if you are not using ARC.
}}
Then call the tag value in the collision detection code.
[self.spriteArray enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop)
{
typeOne *spriteOne = (typeOne *)obj;
if (CGRectIntersectsRect(spriteOne.boundingBox, self.swat.boundingBox))
{
//swat is another sprite
if (spriteOne.tag == numberyouwant){}
NSLog(#"detected");
}
}];
Related
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
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 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?).
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];
}
}
I need help to make an Array, in xcode, to collect 25 existing buttons in a Window(NView) for, for example, change background colors or titles of others buttons when one button is pressed.
Thanks.
This is the Code:
Botones.h
#import <Cocoa/Cocoa.h>
extern const NSString* Nivel[];
extern const NSString* Ayuda[];
extern const NSString* Boleo[];
BOOL Estado[5][5];
int Columna;
int Fila;
//NSColor* Rojo = (NSColor *)redColor;
#interface Botones : NSObject {
IBOutlet id Intents;
IBOutlet id Nivel;
IBOutlet id BoxBot;
NSArray *Arbot;
}
- (IBAction)OrBoton:(id)sender;
Botones.m
#import "Botones.h"
const NSString *Nivel[] = {#"101214",#"0002040507091517192202224",#"01030506080910111314151618192123"};
BOOL Estado[5][5] = {FALSE};
int Columna = 0;
int Fila = 0;
#implementation Botones
- (void)awakeFromNib {
Arbot = [[BoxBot subviews] copy];
}
- (IBAction)OrBoton:(id)sender {
[Intents setIntValue:[sender tag]];
Columna =[sender tag] % 5;
Fila = [sender tag] / 5;
if (Estado[Columna][Fila] == FALSE) {
Estado[Columna][Fila] = TRUE;
[sender setTitle:#"OK"];
//[sender setBackgroundColor:[NSColor redColor]];
}
else {
Estado[Columna][Fila] = FALSE;
[sender setTitle:#""];
//[sender setBackgroundColor:[NSColor greenColor]];
}
if (Fila > 0) {
if (Estado[Columna][Fila - 1] == FALSE) {
Estado[Columna][Fila - 1] = TRUE;
NSLog(#"%#",[BoxBot subviews]);
[[Arbot objectAtIndex:5] setTitle:#"OK"];// <-- Don't changes button's title
}
}
}
If the buttons are the only subviews in the view, you can use this:
//view is a variable pointing to the view containing the buttons
NSArray *buttons = [[view subviews] copy];
If there are other views in the view, you will have to filter them out:
//view is a variable pointing to the view containing the buttons
NSMutableArray *buttons = [[NSMutableArray alloc] initWithCapacity:25];
for(NSView *v in [view subviews]) {
if([v isKindOfClass:[NSButton class]]) [buttons addObject:v];
}
Edit
...
#interface Botones : NSObject {
IBOutlet id Intents;
IBOutlet id Nivel;
IBOutlet id BoxBot;
NSArray *ArBot;
}
...
Botones.m
...
#implementation Botones
- (void)awakeFromNib {
ArBot = [[BoxBot subviews] copy];
/*or
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:25];
for(NSView *v in [BoxBot subviews]) {
if([v isKindOfClass:[NSButton class]]) [array addObject:v];
}
ArBot = [array copy];
[array release];*/
}
...