I'm trying to make a simple app with a button a score counter and a timer but I'm getting some errors
#import <UIKit/UIKit.h>
#interface xyzViewController : UIViewController
{
IBOutlet UILabel *scoreLabel;
IBOutlet UILabel *timerLabel;
NSInteger count;
NSInteger seconds;
NSTimer *timer;
}
- (IBAction)buttonPressed //Expected ';' after method prototype
{
count++
scoreLabel.text = [NSString stringWithFormat:#"Score \n %i", count]
}
#end
If I add ';' I get this instead:
- (IBAction)buttonPressed;
{ //Expected identifier or '('
count++
scoreLabel.text = [NSString stringWithFormat:#"Score \n %i", count]
}
#end
What I must to do?
You are mixing up interface and implementation. The interface contains
the (globally visible) instance variables, properties and method declarations, i.e.
the prototypes:
#interface xyzViewController : UIViewController
{
IBOutlet UILabel *scoreLabel;
IBOutlet UILabel *timerLabel;
NSInteger count;
NSInteger seconds;
NSTimer *timer;
}
- (IBAction)buttonPressed;
#end
The method itself goes into the implementation:
#implementation xyzViewController
- (IBAction)buttonPressed
{
count++;
scoreLabel.text = [NSString stringWithFormat:#"Score \n %i", count];
}
#end
Remarks:
The convention is to start class names with a capital letter: XyzViewController.
Create properties for the outlets (if you don't have them already):
#property (weak, nonatomic) IBOutlet UILabel *scoreLabel;
The compiler synthesizes the instance variable _scoreLabel automatically, so you don't need it in the interface. And then access the property via
self.scoreLabel.text = ....;
Define your interface in the .h iff they are to be public, then create your implementation in the .m. You can't combine them in the .h
You want semicolons inside the function like so:
- (IBAction)buttonPressed {
count++;
scoreLabel.text = [NSString stringWithFormat:#"Score \n %i", count];
}
This is the correct syntax to use.
Related
*.m file*
#import "BNREmployee.h"
#interface BNREmployee ()
#property (weak) IBOutlet NSWindow *window;
#end
#implementation BNREmployee
- (double)yearsOfEmployment
// **Error expected method body**-(void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Do I have a non-nil hireDate?
if (self.hireDate) {
// NSTimeInterval is the same as double
NSDate *now = [NSDate date];
NSTimeInterval secs = [now timeIntervalSinceDate:self.hireDate];
return secs / 31557600.0; // Seconds per year
} else {
return 0;
}
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
#end
*.h file*
#import "BNRPerson.h"
#interface BNREmployee : BNRPerson
#property (nonatomic) unsigned int employeeID;
#property (nonatomic) unsigned int officeAlarmCode;
#property (nonatomic) NSDate *hireDate;
- (double)yearsOfEmployment;
#end
How can i declare "- (double)yearsOfEmploymentsince" since it is declared in another file but while still keeping the "-(void)applicationDidFinishLaunching:(NSNotification *)aNotification {" as the main header???
Your question is a little unclear especially without your .h file to see what this class is a subclass of, but this line: - (double)yearsOfEmployment needs an opening {, that's the "expected method body" problem.
I'm getting the error incompatible pointer types assigning to Deck *__strong from PlayCards *
And i'm not sure why is that. Its in the first method implemented (deck):
#import "CardGameViewController.h"
#import "PlayingCards.h"
#interface CardGameViewController ()
#property (weak, nonatomic) IBOutlet UILabel *cardLabel;
#property (nonatomic) NSUInteger flipsCount;
#property (strong, nonatomic) Deck *deck;
#end
#implementation CardGameViewController
-(Deck *) deck {
if (!_deck) _deck = [[PlayingCards alloc] init];
return _deck;
}
-(void) setFlipsCount:(NSUInteger)flipsCount {
_flipsCount = flipsCount;
self.cardLabel.text = [NSString stringWithFormat:#"Flips:%d", self.flipsCount];
}
- (IBAction)flipCard:(UIButton *)sender {
sender.selected = !sender.isSelected;
self.flipsCount++;
}
#end
This is the header file(nothing going on here):
#import <UIKit/UIKit.h>
//#import "Card.h"
//#import "Deck.h"
//#import "PlayingCards.h"
#interface CardGameViewController : UIViewController
#end
And the PlayingCard class inheriting from Deck class..
this is the PlayingCards.m
#import "PlayingCards.h"
#implementation PlayingCards
#synthesize suit = _suit;
//modifying the contents getter so it will return array with the ranks and rank+suit
-(NSString *) contents {
NSArray *cardsRank = [PlayingCards rankStrings];
return [cardsRank[self.rank] stringByAppendingString:self.suit];
}
//creating a method to make sure we get validated suits
+(NSArray *) validSuit {
return #[#"♠",#"♣",#"♥",#"♦"];
}
//creating calss method to validate the rank
+(NSArray *) rankStrings {
return #[#"?",#"A",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9",#"10",#"J",#"Q",#"K"];
}
//creating a new setter for suit to make sure we get the valitated suits, uding the validateSuit method
-(void) setSuit:(NSString *)suit {
if ([[PlayingCards validSuit] containsObject:suit]) {
_suit = suit;
}
}
//creating new getter for suit to make sure its not empty
-(NSString *) suit {
return _suit? _suit: #"?";
}
//creating a class method to make sure when user set the rank he will will
+(NSUInteger) maxRank {
return [self rankStrings].count - 1;
}
//creating a new setter to the renk to make sure the rank is validates
-(void) setRank:(NSUInteger)rank {
if (rank <= [PlayingCards maxRank]) {
_rank = rank;
}
}
#end
PlayingCards.h
#import "Card.h"
#import "Deck.h"
#interface PlayingCards : Card
#property (strong, nonatomic) NSString *suit;
#property (nonatomic) NSUInteger rank;
+(NSArray *) validSuit;
+(NSUInteger) maxRank;
#end
This line:
if (!_deck) _deck = [[PlayingCards alloc] init];
Should be:
if (!_deck) _deck = [[PlayingCardDeck alloc] init];
If the parent for Card is of class NSObject as you say, and given that PlayingCards inherits from Card, then you can't assign an instance of PlayingCards to a variable of type Deck*. That's what the compiler is telling you.
If you really need to do it, you have to write:
if (!_deck) _deck = (Deck*)[[PlayingCards alloc] init];
It would only be valid because in Objective-C the implementation is given at runtime and which method of which class is called is only decided at runtime when the message is dispatched. However, this pattern is very unusual and you better be certain that PlayingCards is implementing all the selectors that might be called on a Deck instance. A better way would be to use protocols.
You can define a protocol and then use:
id <myProtocol> deck = [[PlayingCards alloc] init];
Put in the protocol all the selectors you need.
Why can't you use this ?
PlayingCards* deck = [[PlayingCards alloc] init];
hey guys,
i'm new to objective-c and i'm having trouble with the memory management. i declared 3 classes, Table, Dataset and my Main class. In my mainclass, i created an Dataset Object and now im trying to pass this Object over to a Tableobject, where i want to store it permanently. but it seems to me that the garbage collector kills the reference before i can use it.
heres some code:
Dataset:
//Dataset.h
#interface Dataset : NSObject {
NSMutableArray* daten;
}
#end
//Dataset.m
#import "Dataset.h"
#import "Datensatz.h"
#implementation Dataset
- (id) init
{
self=[super init];
daten=[[NSMutableArray alloc] init];
return self;
}
Table:
//Table.h
#class Dataset;
#interface Table : NSObject {
Dataset* daten;
}
-(id)init:(NSTableView *)aTableView;
-(id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex;
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView;
#property (retain) Dataset* daten;
#end
//Table.m
#import "Table.h"
#import "Dataset.h"
#impl
ementation Table
#synthesize daten;
-(id)init:(NSTableView*)aTableView
{
self=[super init];
[self setDaten:[Datenmenge alloc]];
return self;
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
{
NSLog(#"anzahl: %d %#",[self.daten anzahl], self.daten);//This is always 0 null
return [daten anzahl];
}
-(void)setDaten:(Dataset *)a
{
NSLog(#"setter: anzahl: %d %#",[a anzahl], a);
[daten release];
daten=[a retain];
NSLog(#"setter: anzahl: %d %#",[daten anzahl], daten);
}
#end
In my mainclass i do the following:
//init method
[self setDaten:[[[Dataset alloc]init]autorelease]];
tabelle=[[Table alloc] init:tableview];
[tabelle setDaten:[self daten]];
Mainclass:
//code.h
//
// MalWiederWasNeuesAppDelegate.h
// MalWiederWasNeues
//
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#class Datenmenge,Graph,Tabelle;
#interface MalWiederWasNeuesAppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
NSToolbarItem *datenKnopf;
NSToolbarItem *speichernKnopf;
NSSlider *scaleSlider;
NSScroller *moveSlider;
NSTableView* tableview;
Graph* graph;
Tabelle* tabelle;
Datenmenge* daten;
}
-(void)tuWas;
- (IBAction)datenHinzufuegen:(id)sender;
- (IBAction)speichern:(id)sender;
#property (assign) IBOutlet NSWindow *window;
#property (assign) IBOutlet NSToolbarItem *datenKnopf;
#property (assign) IBOutlet NSToolbarItem *speichernKnopf;
#property (assign) IBOutlet NSSlider *scaleSlider;
#property (assign) IBOutlet NSScroller *moveSlider;
#property (assign) IBOutlet Graph *graph;
#property (assign) IBOutlet Tabelle *tabelle;
#property (assign) IBOutlet NSTableView* tableview;
#property (retain) Datenmenge* daten;
#end
//code.m
//
// MalWiederWasNeuesAppDelegate.m
// MalWiederWasNeues
//
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "MalWiederWasNeuesAppDelegate.h"
#import "Datenmenge.h"
#import "Graph.h"
#import "Tabelle.h"
#implementation MalWiederWasNeuesAppDelegate
#synthesize window;
#synthesize daten;
-(id) init
{
self.daten=[[Datenmenge alloc]init];
[self.daten datenHinzufuegen:nil];
tabelle=[[Tabelle alloc] init:tableview];
tabelle.daten=daten;
NSLog(#"konstruktor: %f %d",[daten maximum],[daten anzahl]);
//graph.daten=daten;
return self;
}
-(void)tuWas{
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
}
- (IBAction)datenHinzufuegen:(id)sender
{
NSLog(#"%f %d",[daten maximum],[daten anzahl]);
NSLog(#"daten hinzufügen");
}
- (IBAction) speichern:(id)sender
{
NSLog(#"%# %#",daten,[tabelle daten]);
NSLog(#"speichern");
}
#end
I hope this wasnt too much code for you.
when i call a method of "tabelle", my Table object, "daten" does not refer to an Dataset Object. But the NSLogs in "setDaten" show me valid references.
so, what am i doing wrong?
have a good evening,
lukas
You define Daten as a retain type
#property (retain) Dataset* daten; and #synthesize daten;
theres no need to then implement the method
-(void)setDaten:(Dataset *)a thats what #synthesize daten; does
I think theres a lost in translation moment here so ill assume Table == Tabelle and Dataset == Datmenge and I dont see the implementation for your main class.
cast your eye over this too.
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html
Maybe, the daten property of your main class is declared as assign? In that case daten is correct when you call setDaten:, but might have been already autoreleased when you try to access it afterwards.
Also,
-(void)setDaten:(Dataset *)a
{
NSLog(#"setter: anzahl: %d %#",[a anzahl], a);
[daten release];
daten=[a retain];
NSLog(#"setter: anzahl: %d %#",[daten anzahl], daten);
}
is not a good implementation of a setter. If a == daten, then this object will be released (and maybe dealloc'd). You need to check identity of objects when implementing your own setter.
I am trying to make a practice application that takes two entered words (word1, word2) and puts them together to make a compound word. I am very new to this and would like to know the correct way to display these two variables under the action "buttonPressed."
Here's the header file...
#import <UIKit/UIKit.h>
#interface Word_CombinerViewController : UIViewController {
UITextField *word1;
UITextField *word2;
UITextField *display;
UIButton *mashButton;
}
#property (nonatomic, retain) IBOutlet UITextField *word1;
#property (nonatomic, retain) IBOutlet UITextField *word2;
#property (nonatomic, retain) IBOutlet UITextField *display;
#property (nonatomic, retain) IBOutlet UIButton *mashButton;
-(IBAction)textFieldDoneEditing:(id)sender;
-(IBAction)backgroundTap:(id)sender;
-(IBAction)buttonPressed:(id)sender;
#end
And here's the implementation file (.m)...
#import "Word_CombinerViewController.h"
#implementation Word_CombinerViewController
#synthesize word1;
#synthesize word2;
#synthesize display;
#synthesize mashButton;
-(IBAction)textFieldDoneEditing:(id)sender {
[sender resignFirstResponder];
}
-(IBAction)backgroundTap:(id)sender {
[word1 resignFirstResponder];
[word2 resignFirstResponder];
}
-(IBAction)buttonPressed:(id)sender {
NSString *newText = [NSString: #word1, #word2]
display.text = newText;
[newText release]
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[word1 release];
[word2 release];
[display release];
[mashButton release];
[super dealloc];
}
#end
I know this code is probably full of errors, but everyone has gotta start somewhere, right?
Any feedback would be greatly appreciated, thank you!
NSString *newText = [NSString: #word1, #word2]
This code doesn't make any sense. The first part of a message is the receiver, and it won't have any colons in it. The second part is the message itself, i.e. the method name along with any necessary parameters. What you're looking for is:
NSString *newText = [NSString stringWithFormat:#"%#%#", word1, word2];
The -stringWithFormat: method uses a format string (very much like printf()) and a variable number of parameters to fill in the placeholders in the format string.
Also, when you create a string (or any object) using a "convenience method" like this, you shouldn't release it. You didn't retain or alloc or copy it, so it's not your responsibility to release it. You'll want to remove that line from your -buttonPressed method.
Try this:
-(IBAction)buttonPressed:(id)sender {
NSString *newText = [word1.text stringByAppendingString:word2.text]
display.text = newText;
}
Ok, so I have this, but it wont work:
#interface UILabel (touches)
#property (nonatomic) BOOL isMethodStep;
#end
#implementation UILabel (touches)
-(BOOL)isMethodStep {
return self.isMethodStep;
}
-(void)setIsMethodStep:(BOOL)boolean {
self.isMethodStep = boolean;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if(self.isMethodStep){
// set all labels to normal font:
UIFont *toSet = (self.font == [UIFont fontWithName:#"Helvetica" size:16]) ? [UIFont fontWithName:#"Helvetica-Bold" size:16] : [UIFont fontWithName:#"Helvetica" size:16];
id superView = self.superview;
for(id theView in [(UIView *)superView subviews])
if([theView isKindOfClass:[UILabel class]])
[(UILabel *)theView setFont:[UIFont fontWithName:#"Helvetica" size:16]];
self.font = toSet;
}
}
#end
If I take out the getter and setter methods then it doesn't work it tells me I need to create some getter and setter methods (or use #synthesize - but putting #synthesize in the #implementation throws an error too). But with the getter and setter methods I get an EXC_BAD_ACCESS and a crash. Any ideas? Thanks
Tom
It is not possible to add members and properties to an existing class via a category — only methods.
https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/Category.html
One possible workaround is to write "setter/getter-like" methods, that uses a singleton to save the variables, that would had been the member.
-(void)setMember:(MyObject *)someObject
{
NSMutableDictionary *dict = [MySingleton sharedRegistry];
[dict setObject:someObject forKey:self];
}
-(MyObject *)member
{
NSMutableDictionary *dict = [MySingleton sharedRegistry];
return [dict objectforKey:self];
}
or — of course — write a custom class, that inherits from UILabel
Note that nowadays an associated object can be injected during runtime. The Objective C Programming Language: Associative References
Checked all answers and did not find the most common solution:
#import <objc/runtime.h>
static void const *key;
#interface ClassName (CategoryName)
#property (nonatomic) BOOL myProperty;
#end
#implementation ClassName (CategoryName)
- (BOOL)myProperty {
return [objc_getAssociatedObject(self, key) boolValue];
}
- (void)setMyProperty:(BOOL)value {
objc_setAssociatedObject(self, key, #(value), OBJC_ASSOCIATION_RETAIN);
}
#end
swift:
private struct AssociatedKeys {
static var keyName = "keyName"
}
extension Foo {
var bar: Any! {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.keyName)
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.keyName , newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
There is actually a way, which may not be ideal, but does work.
For it to work, you will need to create a category for a class X and can only be used on subclasses of the same X (e.g. category UIView (Background) can be used with class MyView : UIView, but not directly with UIView)
// UIView+Background.h
#interface UIView (Background)
#property (strong, nonatomic) NSString *hexColor;
- (void)someMethodThatUsesHexColor;
#end
// UIView+Background.h
#implementation UIView (Background)
#dynamic hexColor; // Must be declared as dynamic
- (void)someMethodThatUsesHexColor {
NSLog(#"Color %#", self.hexColor);
}
#end
Then
// MyView.m
#import "UIView+Background.h"
#interface MyView : UIView
#property (strong, nonatomic) NSString *hexColor;
#end
#implementation MyView ()
- (void)viewDidLoad {
[super viewDidLoad];
[self setHexColor:#"#BABACA"];
[self someMethodThatUsesHexColor];
}
#end
Using this method, you will need to "redeclare" your properties, but after that, you can do all of its manipulation inside your category.
You could inject an associated object during runtime.
#import <objc/runtime.h>
#interface UIView (Private)
#property (nonatomic, assign) CGPoint initialTouchPoint;
#property (nonatomic, strong) UIWindow *alertWindow;
#end
#implementation UIView (Private)
#dynamic initialTouchPoint, alertWindow;
- (CGPoint)initialTouchPoint {
return CGPointFromString(objc_getAssociatedObject(self, #selector(initialTouchPoint)));
}
- (void)setInitialTouchPoint:(CGPoint)initialTouchPoint {
objc_setAssociatedObject(self, #selector(initialTouchPoint), NSStringFromCGPoint(initialTouchPoint), OBJC_ASSOCIATION_RETAIN);
}
- (void)setAlertWindow:(UIWindow *)alertWindow {
objc_setAssociatedObject(self, #selector(alertWindow), alertWindow, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIWindow *)alertWindow {
return objc_getAssociatedObject(self, #selector(alertWindow));
}
#end
EDIT: Warning: This property would have a unique value for all the instances of the class.
This worked for me, but only because I had only one instance of this class in my app.
#import <AVFoundation/AVFoundation.h>
#interface AVAudioPlayer (AstroAVAudioPlayer)
#property (nonatomic) BOOL redPilot;
#end
#import "AVAudioPlayer+AstroAVAudioPlayer.h"
#implementation AVAudioPlayer (AstroAVAudioPlayer)
BOOL _redPilot;
-(void) setRedPilot:(BOOL)redPilot
{
_redPilot = redPilot;
}
-(BOOL) redPilot
{
return _redPilot;
}
#end
A solution that I found to this was to just give each object that you want flagged a unique tag.
I made a UILabel category to add custom fonts to all my labels but on some i wanted them to be bold so i did this ->
- (void) layoutSubviews {
[super layoutSubviews];
[self addCustomFont];
}
- (void) addCustomFont {
if (self.tag == 22) {
[self setFont:[UIFont fontWithName:SEGOE_BOLD size:self.font.pointSize]];
}else{
[self setFont:[UIFont fontWithName:SEGOE_LIGHT size:self.font.pointSize]];
}
}
It seems as if since Xcode 7 (7.0.1, 7A1001), properties are supported in categories. I noticed that Xcode generates categories now for Core Data subclasses.
For example, I got the files:
Location+CoreDataProperties.h
#import "Location.h"
NS_ASSUME_NONNULL_BEGIN
#interface Location (CoreDataProperties)
#property (nullable, nonatomic, retain) NSNumber *altitude;
#property (nullable, nonatomic, retain) NSNumber *latitude;
#property (nullable, nonatomic, retain) NSNumber *longitude;
#end
NS_ASSUME_NONNULL_END
Location+CoreDataProperties.m
#import "Location+CoreDataProperties.h"
#implementation Location (CoreDataProperties)
#dynamic altitude;
#dynamic latitude;
#dynamic longitude;
#end
So looks like properties in categories might work now. I haven't tested on non-Core Data classes.
What I've noticed is that they do include the category file back into the original class:
Location.h
#interface Location : NSManagedObject
#end
#import "Location+CoreDataProperties.h"
This allows the original class to edit the properties specified by the category.