My tvOS app loads PDFs inside of a scroll view. Each page is currently visible inside of the screen, and you can swipe to scroll through it, but I would like the capability to click the bottom and top buttons to move it up exactly one page at a time. How would I go about doing that?
My code for making the PDF is:
- (CGPDFDocumentRef)openPDFLocal:(NSString *)pdfURL {
NSURL* NSUrl = [NSURL fileURLWithPath:pdfURL];
return [self openPDF:NSUrl];
}
- (CGPDFDocumentRef)openPDFURL:(NSString *)pdfURL {
NSURL* NSUrl= [NSURL URLWithString:pdfURL];
return [self openPDF:NSUrl];
}
- (CGPDFDocumentRef)openPDF:(NSURL*)NSUrl {
CFURLRef url = (CFURLRef)CFBridgingRetain(NSUrl);
CGPDFDocumentRef myDocument;
myDocument = CGPDFDocumentCreateWithURL(url);
if (myDocument == NULL) {
NSLog(#"can't open %#", NSUrl);
CFRelease (url);
return nil;
}
CFRelease (url);
if (CGPDFDocumentGetNumberOfPages(myDocument) == 0) {
CGPDFDocumentRelease(myDocument);
return nil;
}
return myDocument;
}
- (void)drawDocument:(CGPDFDocumentRef)pdfDocument
{
// Get the total number of pages for the whole PDF document
int totalPages= (int)CGPDFDocumentGetNumberOfPages(pdfDocument);
self.pages = totalPages;
NSMutableArray *pageImages = [[NSMutableArray alloc] init];
// Iterate through the pages and add each page image to an array
for (int i = 1; i <= totalPages; i++) {
// Get the first page of the PDF document
CGPDFPageRef page = CGPDFDocumentGetPage(pdfDocument, i);
CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
// Begin the image context with the page size
// Also get the grapgics context that we will draw to
UIGraphicsBeginImageContext(pageRect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
// Rotate the page, so it displays correctly
CGContextTranslateCTM(context, 0.0, pageRect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(page, kCGPDFMediaBox, pageRect, 0, true));
// Draw to the graphics context
CGContextDrawPDFPage(context, page);
// Get an image of the graphics context
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[pageImages addObject:image];
}
// Set the image of the PDF to the current view
[self addImagesToScrollView:pageImages];
}
-(void)addImagesToScrollView:(NSMutableArray*)imageArray {
int height = 0;
for (UIImage *image in imageArray) {
UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
imgView.frame=CGRectMake(200, height, 1520, 1080);
[_scrollView addSubview:imgView];
height += imgView.frame.size.height;
}
}
-(void)viewDidLayoutSubviews {
NSLog(#"%ld", (long)self.pages);
_scrollView.contentSize = CGSizeMake(1920, 1080*self.pages);
}
Related
I am taking a square cropped photo with GPUImageStillCamera and allowing the user to zoom the camera. When the user clicks to take a picture the camera jumps forward for a split second (as if the camera zoomed in even further past the area the user zoomed to and then immediately returns to the correct crop once the image is returned to screen). This only happens when the user has zoomed the camera. If they have not zoomed the camera the flicker/jump does not happen. (The image return has the correct crop whether or not the user has zoomed).
Thoughts?
Creating camera and adding square crop
//Add in filters
stillCamera = [[GPUImageStillCamera alloc] initWithSessionPreset:AVCaptureSessionPreset1280x720 cameraPosition:AVCaptureDevicePositionBack];
stillCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
//Creating a square crop filter
cropFilter = [[GPUImageCropFilter alloc] initWithCropRegion:CGRectMake(0.f, (720.0f/1280.0f)/2.0f, 1.f, (720.0f/1280.0f))];
Image zoom method
-(void)imagePinch:(UIPinchGestureRecognizer *)recognizer{ //Controlling the zoom scale as the user pinches the live preview
if (recognizer.state == UIGestureRecognizerStateBegan) {
zoomOutAdder = 0.0f;
if (currentScale > 2) {
zoomOutAdder = currentScale;
}
}
float addition = (recognizer.scale - lastScale);
if (addition > 0) {
addition = addition *1.7;
}
if (addition < 0) {
addition = addition *(1.7+zoomOutAdder);
}
currentScale = currentScale +addition;
lastScale = recognizer.scale;
if (currentScale < 1) {
currentScale = 1;
}
if (currentScale > 4) {
currentScale =4;
}
if (currentScale == 1) {
zoomOutAdder = 0.0f;
}
cameraImagePreview.transform = CGAffineTransformMakeScale(currentScale, currentScale);
if (recognizer.state == UIGestureRecognizerStateEnded) {
lastScale = 1.0f;
}
Take a photo method
//Adjust crop based on zoom scale of the user
CGFloat zoomReciprocal = 1.0f / currentScale;
CGPoint offset = CGPointMake(((1.0f - zoomReciprocal) / 2.0f), (((1.0f- zoomReciprocal)*(720.0f/1280.0f)) / 2.0f) + ((720.0f/1280.0f)/2)) ;
CGRect newCrop = cropFilter.cropRegion;
newCrop.origin.x = offset.x;
newCrop.origin.y = offset.y;
newCrop.size.width = cropFilter.cropRegion.size.width * zoomReciprocal;
newCrop.size.height = cropFilter.cropRegion.size.height *zoomReciprocal;
cropFilter.cropRegion = newCrop;
*/
//Place photo inside an image preview view for the user to decide if they want to keep it.
[stillCamera capturePhotoAsImageProcessedUpToFilter:cropFilter withOrientation:imageOrientation withCompletionHandler:^(UIImage *processedImage, NSError *error) {
//Pause the current camera
[stillCamera pauseCameraCapture];
//Rest of method
ADDED METHODS
- (void) flipCamera {
if (stillCamera.cameraPosition != AVCaptureDevicePositionFront) {
[UIView animateWithDuration:.65 animations:^{
flipCamera.transform = CGAffineTransformMakeScale(-1, 1);
}];
} else {
[UIView animateWithDuration:.65 animations:^{
flipCamera.transform = CGAffineTransformMakeScale(1, 1);
}];
}
[self performSelector:#selector(rotateCamera) withObject:0 afterDelay:.2];
}
- (void) rotateCamera {
[stillCamera rotateCamera];
//Adjust flash settings as needed
[stillCamera.inputCamera lockForConfiguration:nil];
if (stillCamera.cameraPosition != AVCaptureDevicePositionFront) {
[stillCamera.inputCamera setFlashMode:AVCaptureFlashModeOff];
}
NSAttributedString *attributedFlash =
[[NSAttributedString alloc]
initWithString:#"off"
attributes:
#{
NSFontAttributeName : [UIFont fontWithName:#"Roboto-Regular" size:13.0f],
NSForegroundColorAttributeName : [UIColor colorWithWhite:1 alpha:.55],
NSKernAttributeName : #(.25f)
}];
flashLabel.attributedText = attributedFlash;
[UIView animateWithDuration:.2 animations:^{
[flash setTintColor:[UIColor colorWithWhite:1 alpha:.55]];
}];
[stillCamera.inputCamera unlockForConfiguration];
}
- (void) changeFlash {
if (stillCamera.cameraPosition == AVCaptureDevicePositionFront) {//no flash available on front of camera
return;
}
[stillCamera.inputCamera lockForConfiguration:nil];
if (stillCamera.inputCamera.flashMode == AVCaptureFlashModeOff) {
[stillCamera.inputCamera setFlashMode:AVCaptureFlashModeOn];
[self animateFlashWithTintColor:[UIColor colorWithWhite:1 alpha:1] andString:#"on"];
} else if (stillCamera.inputCamera.flashMode == AVCaptureFlashModeOn) {
[stillCamera.inputCamera setFlashMode:AVCaptureFlashModeOff];
[self animateFlashWithTintColor:[UIColor colorWithWhite:1 alpha:.55] andString:#"off"];
}
[stillCamera.inputCamera unlockForConfiguration];
}
- (void) animateFlashWithTintColor:(UIColor *)color andString:(NSString *)text {
//Set new text
NSAttributedString *attributedFlash =
[[NSAttributedString alloc]
initWithString:text
attributes:
#{
NSFontAttributeName : [UIFont fontWithName:#"Roboto-Regular" size:13.0f],
NSForegroundColorAttributeName : [UIColor colorWithWhite:1 alpha:.55],
NSKernAttributeName : #(.25f)
}];
flashLabel.attributedText = attributedFlash;
float duration = .7;
[UIView animateKeyframesWithDuration:duration delay:0 options:0 animations:^{
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:duration animations:^{
[flash setTintColor:color];
}];
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:.7/duration animations:^{
flash.transform = CGAffineTransformMakeRotation(M_PI);
}];
}completion:^(BOOL finished){
flash.transform = CGAffineTransformIdentity;
}];
}
-(void) usePhoto {
if ([ALAssetsLibrary authorizationStatus] != ALAuthorizationStatusAuthorized){
NSLog(#"Do Not Have Right To Save to Photo Library");
}
//Save Image to Phone Album & save image
UIImageWriteToSavedPhotosAlbum(takenPhoto.image, nil, nil, nil);
//Save Image to Delegate
[self.delegate saveImageToDatabase:takenPhoto.image];
[self performSelector:#selector(dismissCamera) withObject:0 afterDelay:.4];
}
Some additional code showing the creation of the the various camera elements used to capture a photo.
centerPoint = CGPointMake(self.view.frame.size.width/2, (cameraHolder.frame.size.height+50+self.view.frame.size.height)/2);
cameraImagePreview = [[GPUImageView alloc] initWithFrame:CGRectMake(0, 0, cameraHolder.frame.size.width, cameraHolder.frame.size.width)];
[cameraHolder addSubview:cameraImagePreview];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTouch:)];
[cameraImagePreview addGestureRecognizer:tapGesture];
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(imagePinch:)];
[cameraImagePreview addGestureRecognizer:pinchGesture];
float scaleForView = self.view.frame.size.width/720.0;
fullCameraFocusPoint = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 1280*scaleForView)];
fullCameraFocusPoint.center = CGPointMake(cameraHolder.frame.size.width/2, (cameraHolder.frame.size.width/2)+50);
[self.view insertSubview:fullCameraFocusPoint atIndex:0];
takenPhoto = [[UIImageView alloc]initWithFrame:cameraHolder.frame];
takenPhoto.alpha = 0;
[self.view addSubview:takenPhoto];
//Add in filters
stillCamera = [[GPUImageStillCamera alloc] initWithSessionPreset:AVCaptureSessionPreset1280x720 cameraPosition:AVCaptureDevicePositionBack];
stillCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
//Creating a square crop filter
cropFilter = [[GPUImageCropFilter alloc] initWithCropRegion:CGRectMake(0.f, (720.0f/1280.0f)/2.0f, 1.f, (720.0f/1280.0f))];
//Create standard vignette filter
vignetteFilter = [[GPUImageVignetteFilter alloc] init]; //1
vignetteFilter.vignetteCenter = CGPointMake(.5, .5);
vignetteFilter.vignetteStart = 0.4f;
vignetteFilter.vignetteEnd = 1.08f;
//Add filters to photo
[cropFilter addTarget:vignetteFilter];
[stillCamera addTarget:cropFilter];
[vignetteFilter addTarget:cameraImagePreview];
[stillCamera startCameraCapture];
I have a overlay image (.png) on my map that consists of a transparent bit in the middle, and colored sides so the user can only focus on the middle part. However do to the shape of that middle bit, quite a bit is visible at some sides.
I'm trying to detect a tap on the OverlayView so I can ignore it and only accept touches in the designated area.
I followed the following tut at Ray Wenderlich's site for adding the overlay:
The image overlay is drawn like this:
#implementation PVParkOverlayView
- (instancetype)initWithOverlay:(id<MKOverlay>)overlay overlayImage:(UIImage *)overlayImage {
self = [super initWithOverlay:overlay];
if (self) {
_overlayImage = overlayImage;
}
return self;
}
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context {
CGImageRef imageReference = self.overlayImage.CGImage;
//UIImage *imageTest = _overlayImage;
MKMapRect theMapRect = self.overlay.boundingMapRect;
CGRect theRect = [self rectForMapRect:theMapRect];
//orientation testing
//CGContextRotateCTM(context, 0);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, 0.0, -theRect.size.height);
CGContextDrawImage(context, theRect, imageReference);
}
I have a gesture recognizer on my mapview and am trying to detect the tap there:
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
CGPoint tapPoint = [gestureRecognizer locationInView:self.mapView];
CLLocationCoordinate2D tapCoord = [self.mapView convertPoint:tapPoint toCoordinateFromView:self.mapView];
MKMapPoint mapPoint = MKMapPointForCoordinate(tapCoord);
CGPoint mapPointAsCGP = CGPointMake(mapPoint.x, mapPoint.y);
for (id<MKOverlay> overlay in self.mapView.overlays) {
if([overlay isKindOfClass:[PVParkOverlay class]]){
NSLog(#"overlay is present");
/*
MKPolygon *polygon = (MKPolygon*) overlay;
CGMutablePathRef mpr = CGPathCreateMutable();
MKMapPoint *polygonPoints = polygon.points;
for (int p=0; p < polygon.pointCount; p++){
MKMapPoint mp = polygonPoints[p];
if (p == 0)
CGPathMoveToPoint(mpr, NULL, mp.x, mp.y);
else
CGPathAddLineToPoint(mpr, NULL, mp.x, mp.y);
}
if(CGPathContainsPoint(mpr , NULL, mapPointAsCGP, FALSE)){
// ... found it!
NSLog(#"I've found it!");
}
//CGPathRelease(mpr);
*/
}
}
I know that the overlay is there, but since it is a drawn image I can't find a way to convert this to polygon points to use this code (if even possible).
Any other methods I can use for this?
I also found following sample code but the viewForOverlay method is deprecated:
- (void)mapTapped:(UITapGestureRecognizer *)recognizer
{
MKMapView *mapView = (MKMapView *)recognizer.view;
id<MKOverlay> tappedOverlay = nil;
for (id<MKOverlay> overlay in mapView.overlays)
{
MKOverlayView *view = [mapView viewForOverlay:overlay];
if (view)
{
// Get view frame rect in the mapView's coordinate system
CGRect viewFrameInMapView = [view.superview convertRect:view.frame toView:mapView];
// Get touch point in the mapView's coordinate system
CGPoint point = [recognizer locationInView:mapView];
// Check if the touch is within the view bounds
if (CGRectContainsPoint(viewFrameInMapView, point))
{
tappedOverlay = overlay;
break;
}
}
}
NSLog(#"Tapped view: %#", [mapView viewForOverlay:tappedOverlay]);
}
i have a problem with UIScrollview after keyboard shown event, apparently my UITextField moved up just like this :
http://i.stack.imgur.com/ccBSp.png
and this is after keyboard shown :
http://i.stack.imgur.com/X6NU2.png
I did exactly as the example, this is my code :
-(void) keyboardDidShow: (NSNotification *)notif {
if (keyboardVisible) {
NSLog(#"Keyboard is already visible. Ignoring notofication.");
return;
}
//The keyboard wasn't visible before
NSLog(#"Resizing smaller for keyboard");
// Get the size of the keyboard.
NSDictionary* info = [notif userInfo];
NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
// Resize the scroll view to make room for the keyboard
CGRect viewFrame = self.view.frame;
viewFrame.size.height -= keyboardSize.height;
scrollView.frame = viewFrame;
keyboardVisible = YES;}
-(void) keyboardDidHide: (NSNotification *)notif {
if (!keyboardVisible) {
NSLog(#"Keyboard is already hidden. Ignoring notification.");
return;
}
// The keyboard was visible
NSLog (#"Resizing bigger with no keyboard");
//Get the size of the keyboard.
NSDictionary* info = [notif userInfo];
NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
// Reset the height of the scroll view to its original value
CGRect viewFrame = self.view.frame;
viewFrame.size.height += keyboardSize.height;
scrollView.frame = viewFrame;
keyboardVisible = NO;}
Did you try using keyboardWasShown and keyboardWasHidden instead of WillShow and WillHide? Also, I noticed that you are using "UIKeyboardBoundsUserInfoKey" for both Show & Hide. Try "UIKeyboardFrameBeginUserInfoKey" & "UIKeyboardFrameEndUserInfoKey"
Can we save the contents drawn over the pdf , as pdf again , i tried to save the pdf with the contents but with no luck , it saves with blank pdf
the code:
- (void)drawRect:(CGRect)rect
{
NSString *pathToPdfDoc = [[NSBundle mainBundle] pathForResource:#"myPDF" ofType:#"pdf"];
NSURL *pdfUrl = [NSURL fileURLWithPath:pathToPdfDoc];
document = CGPDFDocumentCreateWithURL((__bridge CFURLRef)pdfUrl);
size_t count = CGPDFDocumentGetNumberOfPages (document);// 3
if (count == 0)
{
NSLog(#"PDF needs at least one page");
return;
}
CGRect paperSize = CGRectMake(0.0,0.0,595.28,841.89);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// flip context so page is right way up
CGContextTranslateCTM(currentContext, 0, paperSize.size.height);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CGPDFPageRef page = CGPDFDocumentGetPage (document, 1); // grab page 1 of the PDF
CGContextDrawPDFPage (currentContext, page); // draw page 1 into graphics context
// flip context so annotations are right way up
CGContextScaleCTM(currentContext, 1.0, -1.0);
CGContextTranslateCTM(currentContext, 0, -paperSize.size.height);
////////////////////////////////
[curImage drawAtPoint:CGPointMake(0, 0)];
CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
CGPoint mid2 = midPoint(currentPoint, previousPoint1);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.layer renderInContext:context];
CGContextMoveToPoint(context, mid1.x, mid1.y);
CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
CGContextStrokePath(context);
[super drawRect:rect];
// get a temprorary filename for this PDF
NSString* path = [[NSBundle mainBundle] pathForResource:#"sampleData" ofType:#"plist"];
path = NSTemporaryDirectory();
self.pdfFilePath = [path stringByAppendingPathComponent:[NSString stringWithFormat:#"%d.pdf", [[NSDate date] timeIntervalSince1970] ]];
UIGraphicsBeginPDFContextToFile(#"test.pdf", paperSize, nil);
[#"annotation" drawInRect:CGRectMake(100.0, 100.0, 200.0, 40.0) withFont:[UIFont systemFontOfSize:18.0]];
}
And I tried to close the PDF on button click
- (IBAction)buttonPressed:(UIButton *)button {
UIGraphicsEndPDFContext();
return;
}
But it's not working.
Any help will be greatly appreciated , thanks in advance
figured it out , here is the function to create the pdf with the contents drawn or annotated on it
-(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName: (NSString*)aFilename
{
// Creates a mutable data object for updating with binary data, like a byte array
NSMutableData *pdfData = [NSMutableData data];
// Points the pdf converter to the mutable data object and to the UIView to be converted
UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
// draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
[aView.layer renderInContext:pdfContext];
// remove PDF rendering context
UIGraphicsEndPDFContext();
// Retrieves the document directories from the iOS device
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];
// instructs the mutable data object to write its context to a file on disk
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
NSLog(#"documentDirectoryFileName: %#",documentDirectory);
}
and called the function on button click .
I'm working on a species ID app and would like to populate a layer with sprites based on which animal you select on the main layer. I've made each animal a menu item, and can get my info layer to appear when pressing the button, but how can I set it up so the layer shows the right data depending on which animal you select? The info layer is not a full screen layer, but rather an overlaying layer that only fills about 75% of the screen, which is why I'm going with a layer rather than a scene. I know I can create a new layer for each animal (approx 50) and code it so each button calls its own layer, but I think populating based on which button is pressed would make for cleaner code. If flamingoButton is pressed, sprite is filled with flamingo.png and label is populated with flamingo information. How do I get my info layer to listen to the buttons on the main layer?
MainLayer.m code:
-(id) init
{
if( (self=[super init]))
{
CCMenuItemImage *flamingoButton = [CCMenuItemImage itemFromNormalImage:#"Explore-sign.png" selectedImage:#"Explore-sign.png" target:self selector:#selector(showSecondLayer:)];
flamingoButton.position = CGPointMake(0, 60);
flamingoButton.tag = 101;
CCMenu *menu = [CCMenu menuWithItems:flamingoButton, nil];
[self addChild:menu];
}
return self;
}
-(void) showSecondLayer: (id) sender
{
CCMenuItemImage *item = (CCMenuItemImage *) sender;
int itemID = item.tag;
secondLayer = [SecondLayer node];
secondLayer.position = CGPointMake(0, 700);
[self addChild:secondLayer];
CCMoveTo *moveLayer = [CCMoveTo actionWithDuration:1.0 position:CGPointMake(0, 0)];
[secondLayer runAction:moveLayer];
}
SecondLayer.m (the info layer)
-(id) init
{
if( (self=[super init]))
{
//Change this sprite image based on button from main layer. I don't have it coded in yet, but I understand the concept of putting a variable in the file string using %# or %d
CCSprite *infoCard = [CCSprite spriteWithFile:#"species1.png"];
infoCard.anchorPoint = CGPointMake(0.5, 0);
infoCard.position = CGPointMake(512, 0);
[self addChild:infoCard];
}
return self;
}
Ok, this might work:
//MainLayer:
-(id) init
{
if( (self=[super init]))
{
CCMenuItem *flamingoButton = [CCMenuItemImage itemFromNormalImage:#"Explore-sign.png"
selectedImage:#"Explore-sign.png"
target:self
selector:#selector(showSecondLayer:)];
flamingoButton.position = ccp(0, 60);
flamingoButton.tag = 1;
CCMenu *menu = [CCMenu menuWithItems:flamingoButton, nil];
[self addChild:menu];
}
return self;
}
-(void) showSecondLayer: (CCMenuItem*) sender
{
secondLayer = [SecondLayer layerWithTag:[sender tag]];
secondLayer.position = ccp(0, 700);
[self addChild:secondLayer];
CCMoveTo *moveLayer = [CCMoveTo actionWithDuration:1.0 position:ccp(0, 0)];
[secondLayer runAction:moveLayer];
}
//Second Layer.h
+(id)layerWithTag:(NSInteger)aTag;
-(id) initWithTag:(NSInteger)aTag;
//Second Layer.m:
+(id)layerWithTag:(NSInteger)aTag {
return [[[SecondLayer alloc] initWithTag:aTag] autorelease];
}
-(id) initWithTag:(NSInteger)aTag
{
if( (self=[super init]))
{
//Change this sprite image based on button from main layer. I don't have it coded in yet, but I understand the concept of putting a variable in the file string using %# or %d
CCSprite *infoCard = [CCSprite spriteWithFile:[NSString stringWithFormat:#"species%d.png", aTag]];
infoCard.anchorPoint = ccp(0.5, 0);
infoCard.position = ccp(512, 0);
[self addChild:infoCard];
}
return self;
}
EDIT:
Even though the previous solution works, it's not intuitive, and I feel I am breaking some OOP concepts. Most importantly, it is only useable given that your info about the animal can be retrieved using a single int! .. Using it this way is a BIT better, it's totally up to you to decide:
Ehm, so, I would suggest you set up an Entity Class first:
//AnimalResources.h
#import "Blahblahblah"
//Give it a good name, I was always bad at Science:
#interface AnimalResources {
//load all your properties:
NSString* info;
CCSprite* sprite;
...
}
//set the properties as needed:
//Make sure you properly manage this!! It is retained!
#property (nonatomic, retain) CCSprite* sprite;
...
//method prototype (signature.. am not sure)
//Now, we shall build on the fact that it will be easy for you to map an integer to the right resources:
+(id)animalResourcesWithTag:(NSInteger)aTag;
-(id)initAnimalResourcesWithTag:(NSInteger)aTag;
//AnimalResources.m:'
#synthesize sprite, ... ;
+(id)animalResourcesWithTag:(NSInteger)aTag {
[[[AnimalResources alloc] initAnimalResourcesWithTag:aTag] autorelease];
}
-(id)initAnimalResourcesWithTag:(NSInteger)aTag {
if ((self = [super init])) {
//use tag to retrieve the resources:
//might use the stringFormat + %d approach, or have a dictionary/array plist, that maps an int to a dictionary of resource keys.
//string way of doing things:
self.sprite = [CCSprite spriteWithFile:[NSString stringWithFormat:#"species%d.png", aTag]];
...
//Dictionary: dict/array is an NSDictionary/NSArray read from disk sometime. Don't read it here, since it
//will read the file from disk many times if you do --> BAD. I could explain a rough way to do that if you
//need help
animalDict = [dict objectForKey:[NSString stringWithFormat:#"species%d.png", aTag]];
//OR...
animalDict = [array objectAtIndex:aTag];
//better to have #"spriteNameKey" defined in a macro somewhere: #define kAnimalResourceKeySprite #"SpriteKey"
self.sprite = [CCSprite spriteWithFile:[animalDict objectForKey:#"SpriteNameKey"]];
....
}
return self;
}
Phew! Then .. you guessed it!
-(void) showSecondLayer: (CCMenuItem*) sender
{
secondLayer = [SecondLayer layerWithAnimalResources:[AnimalResources animalResourcesWithTag:[sender tag]]];
secondLayer.position = ccp(0, 700);
[self addChild:secondLayer];
CCMoveTo *moveLayer = [CCMoveTo actionWithDuration:1.0 position:ccp(0, 0)];
[secondLayer runAction:moveLayer];
}
//Second Layer.h
+(id)layerWithAnimalResources:(AnimalResources*)resource;
-(id)initWithAnimalResources:(AnimalResources*)resource;
//Second Layer.m:
+(id)layerWithAnimalResources:(AnimalResources*)resource {
return [[[SecondLayer alloc] initWithAnimalResources:aTag] autorelease];
}
-(id) initWithAnimalResources:(AnimalResources*)resource
{
if( (self=[super init]))
{
//Change this sprite image based on button from main layer. I don't have it coded in yet, but I understand the concept of putting a variable in the file string using %# or %d
CCSprite *infoCard = [resource sprite];
infoCard.anchorPoint = ccp(0.5, 0);
infoCard.position = ccp(512, 0);
[self addChild:infoCard];
}
return self;
}
Give each menu item a unique id. In the method which you invoke on the tap of the button, you can reference the id of the sender. Use this id to populate the new layer with the unique information.
- (void) buttonPressed: (id) sender
{
MenuItem* item = (MenuItem*) sender;
int itemID = item.tag;
// Get unique data based on itemID and add new layer
}
EDIT: Per your code updates
-(void) showSecondLayer: (id) sender
{
CCMenuItemImage *item = (CCMenuItemImage *) sender;
int itemID = item.tag;
secondLayer = [SecondLayer node];
[secondLayer setItem: itemID]; // ADDED
secondLayer.position = CGPointMake(0, 700);
[self addChild:secondLayer];
CCMoveTo *moveLayer = [CCMoveTo actionWithDuration:1.0 position:CGPointMake(0, 0)];
[secondLayer runAction:moveLayer];
}
SecondLayer.m (the info layer)
-(id) init
{
if( (self=[super init]))
{
// Removed
}
return self;
}
-(void) setItem: (int) item
{
CCSprite *infoCard = [CCSprite spriteWithFile:[NSString stringWithFormat:#"species%d", item]];
infoCard.anchorPoint = CGPointMake(0.5, 0);
infoCard.position = CGPointMake(512, 0);
[self addChild:infoCard];
}