Question

Hei,

just starting to get into C4 and so far my experience has been great. I'm replicating the taking a photo with the camera-example at the moment and for some reason when I do everything as described in the tutorial (http://www.c4ios.com/tutorials/takingSnapshots) I get the following mistake: "No visible @interface for 'TakePhoto' declares the selector 'listenFor:from Object:'" (Take Photo is the file I'm working in) I think I have to declare "imageWasCaptured" in the class definition but I don't know as what? Any suggestions?

updated: here is the code https://github.com/susemiessner/Urban-Alphabets/tree/master/urbanAlphabets or just plain copied TakePhoto.h

#import "C4CanvasController.h"

@interface TakePhoto : C4CanvasController

@end

TakePhoto.m

    #import "TakePhoto.h"
    #define NavBarHeight 42
    #define TopBarFromTop 20

    @interface TakePhoto ()

    @end

    @implementation TakePhoto {
        //common variables
        UIColor *navBarColor;
        UIColor *buttonColor;
        UIColor *typeColor;

        //top toolbar
        C4Shape *topNavBar;
        C4Font *fatFont;
        C4Label *takePhoto;



        //camera
        C4Camera *cam;

        //bottom Toolbar
        C4Shape *bottomNavBar;
        C4Button *takePhotoButton;
    }
    -(void) setup{
        navBarColor=[UIColor colorWithRed:0.96875 green:0.96875 blue:0.96875 alpha:1];
        buttonColor= [UIColor colorWithRed:0.8984275 green:0.8984275 blue:0.8984275 alpha:1];
        typeColor=[UIColor colorWithRed:0.19921875 green:0.19921875 blue:0.19921875 alpha:1];

        [self topBarSetup];
        [self bottomBarSetup];
        [self cameraSetup];

    }
    -(void)topBarSetup{
        topNavBar=[C4Shape rect:CGRectMake(0, TopBarFromTop, self.canvas.width, NavBarHeight)];
        topNavBar.fillColor=navBarColor;
        topNavBar.lineWidth=0;
        [self.canvas addShape:topNavBar];


        fatFont=[C4Font fontWithName:@"HelveticaNeue-Bold" size:17];
        takePhoto = [C4Label labelWithText:@"Take Photo" font:fatFont];
        takePhoto.center=topNavBar.center;
        [self.canvas addLabel:takePhoto];}

    -(void)cameraSetup{
        cam = [C4Camera cameraWithFrame:CGRectMake(0,TopBarFromTop+NavBarHeight, self.canvas.width, self.canvas.height-(2*NavBarHeight+TopBarFromTop))];
        [self.canvas addCamera:cam];
        [cam initCapture];
        //tapping to take image
        [self addGesture:TAP name:@"capture" action:@"capturedImage"];
        [self numberOfTouchesRequired:1 forGesture:@"capture"];
//the following line is where I get the error
        [self listenFor:@"imageWasCaptured" fromObject:@"putCapturedImageOnCanvas"];
    }
    -(void) bottomBarSetup{
        bottomNavBar=[C4Shape rect:CGRectMake(0, self.canvas.height-(NavBarHeight), self.canvas.width, NavBarHeight)];
        bottomNavBar.fillColor= navBarColor;
        bottomNavBar.lineWidth=0;
        [self.canvas addShape:bottomNavBar];

        takePhotoButton=[UIButton buttonWithType: ROUNDEDRECT];
        [takePhotoButton setTitle:@"TakePhoto" forState:UIControlStateNormal];
        takePhotoButton.frame=CGRectMake(self.canvas.width/2-50, self.canvas.height-(NavBarHeight), 100, NavBarHeight);
        takePhotoButton.backgroundColor=buttonColor;
        takePhotoButton.tintColor=typeColor;
        [self.canvas addSubview:takePhotoButton];

    }

    -(void) takingPhoto{
        [cam captureImage];
    }
    -(void) captureImage{
        [cam captureImage];
    }
    -(void)putCapturedImageOnCanvas{
        C4Image *img = cam.capturedImage;
        img.width=240;
        img.center=CGPointMake(self.canvas.width*2/3, self.canvas.center.y);

    }


    @end
Was it helpful?

Solution

To get your concept working there are a couple of holes in your approach that will prevent you from seeing anything actually happen. Your question is definitely one of them.

To answer your question:

listenFor:fromObject: is unrecognized because it actually doesn't exist.

The intention of listenFor methods is so that your app, or a specific object, can react to a notification or an action happening somewhere else in the application. So what you want to do is run a method when something happens.

Your method should be:

[self listenFor:@"imageWasCaptured" fromObject:cam andRunMethod:@"methodName"];

You want to listen for when the camera has finished capturing and then do something with that...


Other things I noticed...

If you want to use a C4Button, then the following:

takePhotoButton=[UIButton buttonWithType: ROUNDEDRECT];
[takePhotoButton setTitle:@"TakePhoto" forState:UIControlStateNormal];

Should be:

takePhotoButton = [C4Button buttonWithType:ROUNDEDRECT];
[takePhotoButton setTitle:@"TakePhoto" forState:NORMAL];

Also, you're subclassing C4CanvasController. To get your TakePhoto object's view onto the main canvas you need to create it properly.

To do this in the main canvas I wrote the following in my workspace:

#import "C4Workspace.h"
#import "TakePhoto.h"

@implementation C4WorkSpace {
    TakePhoto *tp;
}

-(void)setup {
    tp = [TakePhoto new];
    tp.canvas.frame = CGRectMake(30,
                                 30,
                                 self.canvas.width - 60,
                                 self.canvas.height - 60);
    tp.canvas.shadowOffset = CGSizeMake(10,10);
    tp.canvas.shadowOpacity = 1.0f;
    tp.canvas.userInteractionEnabled = YES;
    [tp setup];
    tp.mainCanvas = self.canvas;
    [self.canvas addSubview:tp.canvas];
}
@end

And, finally, to get your camera's image onto the main canvas, I had do bridge a little. I created a property in TakePhoto that lets me set the main canvas in your new controller. You'll notice in the code above the line that states tp.mainCanvas = self.canvas...

The TakePhoto header now looks like:

#import "C4CanvasController.h"

@interface TakePhoto : C4CanvasController
@property (readwrite, strong) C4Window *mainCanvas;
@end

And the putImageOnCanvas method now looks like:

-(void)putCapturedImageOnCanvas{
    C4Image *img = cam.capturedImage;
    img.width=240;
//    img.center=CGPointMake(self.canvas.width*2/3, self.canvas.center.y);
    img.center = CGPointMake([C4Math randomInt:self.mainCanvas.width], [C4Math randomInt:self.mainCanvas.height]);
    [self.mainCanvas addImage:img];
    [self.mainCanvas bringSubviewToFront:self.canvas];
}

The last two lines put the image on the canvas and then make sure that the TakePhoto canvas (i.e. the one with the camera) is brought to the foreground so the newly added image doesn't occlude it.

Because you're using a subclass of a C4CanvasController your app structure looks like:

C4WorkSpace.canvas > TakePhoto.canvas > Camera

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top