Method definition for 'addTask:' not found - objective-c

I was making a program called iTahDoodle when i got an error, My error is "Method definition for 'addTask:' not found"
Here is my code:
#import "AppDelegate.h"
// Helper function to fetch the path to our ro-do data stored on disk
NSString *docPath()
{
NSArray *pathList = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [[pathList objectAtIndex:0] stringByAppendingPathComponent:#"data.td"];
}
#implementation AppDelegate
#pragma mark - Application delegate callbacks
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//attempt to load an existing to-do dataset from an array stored to disk
NSArray *plist = [NSArray arrayWithContentsOfFile:docPath()];
if (plist) {
//if there was a dataset available, copy it into our instance variable
tasks = [plist mutableCopy];
} else {
//otherwise, just create an empty one to get us started.
tasks = [[NSMutableArray alloc] init];
}
//create and configure the uiwondow instance
//a cgrect is a struct with an origin (x,y) and size (width,height)
CGRect windowFrame = [[UIScreen mainScreen] bounds];
UIWindow *theWindow = [[UIWindow alloc] initWithFrame:windowFrame];
[self setWindow:theWindow];
//define the frame rectangles of three UI elements
//CGrectMake () creates a CGRect from (x,y, width, height}
CGRect tableFrame = CGRectMake(0, 80, 320, 380);
CGRect fieldFrame = CGRectMake(20, 40, 200, 31);
CGRect buttonFrame = CGRectMake(228, 40, 72, 31);
// create and configure the table view
taskTable = [[UITableView alloc] initWithFrame:tableFrame
style:UITableViewStylePlain];
[taskTable setSeparatorStyle:UITableViewCellSeparatorStyleNone];
//create and configure the text field where new tasks will be typed
taskField = [[UITextField alloc] initWithFrame:fieldFrame];
[taskField setBorderStyle:UITextBorderStyleRoundedRect];
[taskField setPlaceholder:#"Type a task, Tap Insert"];
// create and configure a rounded rect insert button
insertButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[insertButton setFrame:buttonFrame];
//buttons behave using a target/action callback
// configure the insert button's action to call this object's -addTask: method
[insertButton addTarget:self
action:#selector(addTask:)
forControlEvents:UIControlEventTouchUpInside];
//give the button a title
[insertButton setTitle:#"Insert"
forState:UIControlStateNormal];
// add our three ui elements to the window
[[self window] addSubview:taskTable];
[[self window] addSubview:taskField];
[[self window] addSubview:insertButton];
// finalize the window and put it on the screen
[[self window] setBackgroundColor:[UIColor whiteColor]];
[[self window] makeKeyAndVisible];
return YES;
}
I believe that is all the code you will need to see, but if it isn't add a comment.

You need to implement the method in your .m file.

Related

Can't see a new subview

All I am trying to do is add a new view to the content view of my NSWindow instance. When I do the following I do not see the new view (which should be black and take up the entire window). What am I doing wrong?
(done in response to a button click)
NSRect frameRect = [self.window frame];
frameRect.origin = NSZeroPoint;
NSView *view = [[NSView alloc] initWithFrame:frameRect];
view.wantsLayer = YES;
view.layer.backgroundColor = [NSColor blackColor].CGColor;
[self.window.contentView addSubview:view];
I've set up a simple project with a push button inside a ViewController and got a warning for accessing self.window. When using self.view.windowthe warning went away and your provided code works as expected.
Updated code
NSRect frameRect = [self.view.window frame];
frameRect.origin = NSZeroPoint;
NSView *view = [[NSView alloc] initWithFrame:frameRect];
view.wantsLayer = YES;
view.layer.backgroundColor = [NSColor blackColor].CGColor;
[self.view.window.contentView addSubview:view];
Update
Assuming that you're using an instance of WindowController where you're adding a button programmatically, your code works as expected.
#implementation WindowController
- (void)windowDidLoad
{
[super windowDidLoad];
CGRect buttonRect = CGRectMake(self.window.frame.size.width / 2 - 50,
self.window.frame.size.height / 2,
100,
50);
NSButton *button = [[NSButton alloc] initWithFrame:NSRectFromCGRect(buttonRect)];
[button setTitle: #"Click me!"];
[button setTarget:self];
[button setAction:#selector(buttonPressed)];
[self.window.contentView addSubview:button];
}
- (void)buttonPressed
{
NSRect frameRect = [self.window frame];
frameRect.origin = NSZeroPoint;
NSView *view = [[NSView alloc] initWithFrame:frameRect];
view.wantsLayer = YES;
view.layer.backgroundColor = [NSColor blackColor].CGColor;
[self.window.contentView addSubview:view];
}
An instance of NSViewController ain't got a property of window - only NSWindowController has one.

cocoa detect object in mouse clicked

I created a custom object (NSImageView) to display images and I use addSubview: self.view to add
I want to determine if the mouse click in it.
How do I do?
Thank you.
NSImage *Image = [NSImage imageNamed:#"oneimage.jpg"];
NSImageView *ImageView = [[NSImageView alloc] init];
[ImageView setImage:Image];
[self.window addSubview:ImageView];
[ImageView_IconToAdd setAcceptsTouchEvents:YES];
[ImageView_IconToAdd setWantsRestingTouches:YES];
-(void)mouseDragged:(NSEvent *)theEvent {
id clickedObject = [self hitTest:[theEvent locationInWindow]];
if ([clickedObject isKindOfClass:[NSImageView class]]) {
NSLog(#"Clicked an ImageView");
} else if ([clickedObject isKindOfClass:[NSView class]]) {
NSLog(#"Clicked a WebView");
}
}
But error:
No visible #interface for 'WindowImage' declares the selector 'hitTest:'
And can't get Object!

Add UItextfield on button click

I'm new to Objective-c and i've reached an issue.
I'm trying to make a small scoreboard app, for learning more of the language.
Here is a small part of the app.
What i want it it to do is to add a new UItext field when you press the add button. So on button click it looks like this.
How can i add multiple UItextfields on button click in objective-c?
This is a very simple requirement. All you have to do is to create and add the new "Player Number" text field and "Fouls" label each time you tap the "Add" button. After this, move the "Add" button downwards and that's it. Here is some example code.
First of all, to keep things simple I created a UIViewController subclass to hold the "Player Number" text box and the "Fouls" label to make it easy to create them multiple times. Here is the class:
// The .h file
#import <UIKit/UIKit.h>
#interface LLPlayerViewController : UIViewController
// This is a very simple class with no public properties or methods
#end
// The .m file
#implementation LLPlayerViewController
-(void)loadView {
// Create the initial view
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 190, 25)];
self.view = view;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// PlayerNumber Text Field
UITextField *playerNumberField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 120, 20)];
playerNumberField.placeholder = #"PlayerNumber";
playerNumberField.borderStyle = UITextBorderStyleLine;
[self.view addSubview:playerNumberField];
// Fouls Label
UILabel *foulsLabel = [[UILabel alloc] initWithFrame:CGRectMake(135, 0, 50, 20)];
foulsLabel.text = #"0";
[self.view addSubview:foulsLabel];
}
#end
Then, in the main View Controller I create instances of that class and add them to the view each time I press the "Add" button. Here is some sample code:
// Don't forget to import the previous class
#import "LLPlayerViewController.h"
- (void)viewDidLoad
{
[super viewDidLoad];
// Inside viewDidLoad add the following code:
self.playersArray = [[NSMutableArray alloc] init];
// PLAYER Header
UILabel *playerLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 25, 80, 20)];
playerLabel.text = #"PLAYER";
[self.view addSubview:playerLabel];
// FOULS Header
UILabel *foulsLabel = [[UILabel alloc] initWithFrame:CGRectMake(145, 25, 80, 20)];
foulsLabel.text = #"FOULS";
[self.view addSubview:foulsLabel];
// Add player button
self.addPlayerButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.addPlayerButton.frame = CGRectMake(30, 60, 80, 30);
[self.addPlayerButton setTitle:#"Add" forState:UIControlStateNormal];
[self.addPlayerButton addTarget:self action:#selector(addPlayerTapped:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.addPlayerButton];
}
// This method will get called each time the user taps the "Add" button
-(void)addPlayerTapped:(id)sender {
NSLog(#"Adding Player");
self.yOffset = 60.0;
LLPlayerViewController *llVC = [[LLPlayerViewController alloc] init];
llVC.view.alpha = 0.0;
[self.playersArray addObject:llVC];
[self.view addSubview:llVC.view];
[self repositionFields];
}
// This method is responsible for repositioning the views
-(void)repositionFields {
// Reposition each view in the array
for (LLViewController *llVC in self.playersArray) {
CGRect frame = llVC.view.frame;
frame.origin.x = 15;
frame.origin.y = self.yOffset;
llVC.view.frame = frame;
self.yOffset += frame.size.height;
}
// Add some animations to make it look nice
[UIView animateWithDuration:0.3 animations:^{
CGRect frame = self.addPlayerButton.frame;
frame.origin.y = self.yOffset;
self.addPlayerButton.frame = frame;
} completion:^(BOOL finished) {
LLViewController *llVC = [self.playersArray lastObject];
llVC.view.alpha = 1.0;
}];
}
This code was tested on an iPad simulator but I believe it would also work on an iPhone. The code is straight-forward and self explanatory but let me know if you have any more questions.
Hope this helps!

long delay when calling cocoa method

I have a method for saving the contents of a UIScrollView with a user-supplied filename.
Everything works fine, except that there is a long delay when the user taps the "Save" button and the method is called. I can't work out what's calling the delay, nor find a way to indicate to the user that everything is ok, we have not crashed!
I thought the delay was occurring during the renderInContext, but it seems to be happening a lot earlier, when there is not much else going on.
Here is the troublesome method:
- (void)captureViewImage {
NSLog(#"captureViewImage called!");
// long delay happens here!
fileNamer.title = #"Preparing to save...";
// get user's file name
NSString *fileName = fileNamer.fileNameField.text;
// dismiss keyboard
[fileNamer.fileNameField resignFirstResponder];
// dismiss modal view
[self dismissFileNamingFormSheet];
CGRect oldFrame = mainScrollView.frame;
// capture off-screen content
mainScrollView.frame = CGRectMake(0, 0, 1024, 1432);
// make screenshot
UIGraphicsBeginImageContext(mainScrollView.bounds.size);
[mainScrollView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// save screenshot in docs dir
NSData *pngData = UIImagePNGRepresentation(screenImg);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
[pngData writeToFile:[documentsDir stringByAppendingPathComponent:fileName]
options:NSDataWritingAtomic error:nil];
// revert scroll view
mainScrollView.frame = oldFrame;
}
fileNamer is a custom class that throws up a UIModalPresentationFormSheet asking the user to supply a name for the file. It looks like this:
#implementation FileNamingViewController
#synthesize fileNameField, newFileName;
- (id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil parent:(TestDriveViewController *) myParent {
if (self == [super initWithNibName:#"FileNamingViewController" bundle:nil]) {
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc]
initWithTitle:#"Save"
style:UIBarButtonItemStyleDone
target:myParent
action:#selector(captureViewImage)];
self.navigationItem.rightBarButtonItem = rightButton;
[rightButton release];
UIBarButtonItem *leftButton = [[UIBarButtonItem alloc]
initWithTitle:#"Cancel"
style:UIBarButtonItemStyleBordered
target:myParent
action:#selector(dismissFileNamingFormSheet)];
self.navigationItem.leftBarButtonItem = leftButton;
[leftButton release];
self.title = #"Save As?";
}
return self;
}
// UITextFieldDelegate
- (void)textFieldDidEndEditing:(UITextField *)textField {
[fileNameField resignFirstResponder];
}
- (void)viewDidLoad {
[fileNameField becomeFirstResponder];
[super viewDidLoad];
}
fileNamer is initialized and released as follows:
- (void)presentFileNamingFormSheet {
fileNamer = [[FileNamingViewController alloc]
initWithNibName:nil
bundle:nil
parent:self];
fileNamingNavCtrl = [[UINavigationController alloc]
initWithRootViewController:fileNamer];
fileNamingNavCtrl.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:fileNamingNavCtrl
animated:YES];
// resize modal form sheet
fileNamingNavCtrl.view.superview.frame = CGRectMake(0, 0, 540, 115);
// reposition modal form sheet
CGPoint position = CGPointMake(self.view.center.x, self.view.center.y - 50);
fileNamingNavCtrl.view.superview.center = position;
}
- (void)dismissFileNamingFormSheet {
[fileNamer release];
[fileNamingNavCtrl release];
[self dismissModalViewControllerAnimated:YES];
}
Output from Time Profiler:
Running (Self) Symbol Name
1109.0ms 37.0% argb32_image_mark_rgb32
328.0ms 10.9% blkclr
171.0ms 5.7% lo_alltraps
134.0ms 4.4% pmap_enter
116.0ms 3.8% png_write_find_filter
102.0ms 3.4% pmap_remove_range
55.0ms 1.8% pmap_get_mapwindow
47.0ms 1.5% vm_page_lookup
47.0ms 1.5% ml_set_interrupts_enabled
43.0ms 1.4% vm_page_grab
38.0ms 1.2% OSAddAtomic64
34.0ms 1.1% hw_lock_to
31.0ms 1.0% alphaProviderGetBytes
30.0ms 1.0% hw_lock_unlock
26.0ms 0.8% png_read_filter_row
25.0ms 0.8% deflateInit_
23.0ms 0.7% vm_map_lookup_entry
23.0ms 0.7% adler32
22.0ms 0.7% memory_object_recover_named
I found out what was causing this. The image I was saving contained a lot of transparent views. For example, I had a lot of UIButtons which had an alpha value of 0.05 to make them more or less disappear. I didn't realise I could just set the button type to custom to make it invisible (I created the view along time ago). Once I set everything in my image view to have an alpha value of 1.0, the saving process became a lot quicker.

Cocoa Touch: Creating and Adding Custom View

I create a custom view in cocoa touch that is superclassed by UIView and in my main controller I initialize it and then add it as a subview to the main view, but when I add it to the main view it calls my initializer method again and causes an infinite loop. Am I going about creating my custom view wrong?
Here is the mainView
- (void)loadView {
UIImage* tempImage = [UIImage imageNamed: #"image1.jpg"];
CustomImageContainer *testImage = [[CustomImageContainer alloc] initWithImage: tempImage andLabel: #"test image" onTop: true atX: 10 atY: 10];
[self.view addSubview: testImage];
}
and the CustomImageContainer
-(CustomImageContainer *) initWithImage: (UIImage *)imageToAdd andLabel: (NSString *)text onTop: (BOOL) top atX: (int) x_cord atY: (int) y_cord{
UIImageView *imageview_to_add = [[UIImageView alloc] initWithImage: imageToAdd];
imageview_to_add.frame = CGRectMake(0, 0, imageToAdd.size.width, imageToAdd.size.height);
UILabel *label_to_add = [[UILabel alloc] init];
label_to_add.text = text;
label_to_add.alpha = 50;
label_to_add.backgroundColor = [UIColor blackColor];
label_to_add.textColor = [UIColor whiteColor];
[self addSubview: imageview_to_add];
self.frame = CGRectMake(x_cord, y_cord, imageToAdd.size.width, imageToAdd.size.height);
if (top) {
label_to_add.frame = CGRectMake(0, 0, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
//[self addSubview: label_to_add];
}
else {
label_to_add.frame = CGRectMake(0,.2 * imageview_to_add.frame.size.height, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
}
[self addSubview: label_to_add];
[super init];
return self;
}
Why did you put the [super init] statement at the end of the initializer ? When subclassing, you usually put this statement at the start of method.
For UIView subclasses, the designated initializer when creating views in code is initWithFrame:, so you should call it before adding the label and the image. You can use the image to compute the frame needed by the custom view.
-(CustomImageContainer *) initWithImage: (UIImage *)imageToAdd andLabel: (NSString *)text onTop: (BOOL) top atX: (int) x_cord atY: (int) y_cord{
// The view will gets its frame to the size of the image
UIImageView *imageview_to_add = [[UIImageView alloc] initWithImage: imageToAdd];
// Call the designated initializer
CGRect frame = CGRectMake(x_cord, y_cord, imageToAdd.size.width, imageToAdd.size.height);
self = [super initWithFrame:frame];
[self addSubview: imageview_to_add];
UILabel *label_to_add = [[UILabel alloc] init];
label_to_add.text = text;
label_to_add.alpha = 50;
label_to_add.backgroundColor = [UIColor blackColor];
label_to_add.textColor = [UIColor whiteColor];
if (top) {
label_to_add.frame = CGRectMake(0, 0, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
}
else {
label_to_add.frame = CGRectMake(0,.2 * imageview_to_add.frame.size.height, imageview_to_add.frame.size.width, imageview_to_add.frame.size.height);
}
[self addSubview: label_to_add];
return self;
}
If you still have an infinite loop, pause the debugger and search for the recurrent method pattern in the stack trace. This pattern will gives you where the code enters the infinite loop.