"Missing context for method declaration" for overridden description method - objective-c

Am getting a "Missing context for method declaration" for my overridden description method. Can you tell what's wrong with the code?
#import <Foundation/Foundation.h>
#import "BNRItem.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
// Create a mutable array object, store its address in items variable
NSMutableArray *items = [[NSMutableArray alloc]init];
BNRItem *p = [[BNRItem alloc]init];
NSLog(#"%# %# %# %d", [p itemName], [p dateCreated], [p serialNumber], [p valueInDollars]);
// This creates a new NSString, "Red Sofa" and gives it to the BNRItem
[p setItemName:#"Red Sofa"];
// This creates a new NSString, "A1B2C" and gives it to the BNRItem
[p setSerialNumber:#"A1B2C"];
// We send the value 100 to be used as the valueInDollars of this BNRItem
[p setValueInDollars:100];
// Destroy the array pointed to by items
items = nil;
}
return 0;
}
-(NSString *)description // Missing context for method declaration
{
NSString *descriptionString =
[[NSString alloc]initWithFormat:#"%# (%#): Worth $%d, recorded on %#",
itemName;
serialNumber;
valueInDollars;
dateCreated];
return descriptionString;
}
BNRItem.m
#import "BNRItem.h"
#implementation BNRItem
-(void)setItemName:(NSString *)str {
itemName = str;
}
-(NSString *)itemName {
return itemName;
}
-(void)setSerialNumber:(NSString *)str {
serialNumber = str;
}
-(NSString *)serialNumber {
return serialNumber;
}
-(void)setValueInDollars:(int)i {
valueInDollars = i;
}
-(int)valueInDollars {
return valueInDollars;
}
-(NSDate *)dateCreated {
return dateCreated;
}
-(NSString *)description
{
NSString *descriptionString =
[[NSString alloc]initWithFormat:#"%# (%#): Worth $%d, recorded on %#",
itemName,
serialNumber; // Expected "]"
valueInDollars, // Expression result unused
dateCreated]; //Extraneous "]" before ";"
return descriptionString;
}
#end

Your method appears to be free floating inside main.m. An instance method needs to be placed inside the implementation section of a class. (between #implementation and #end).
My guess is that you should move that code into BNRItem.m.

If you have something like a char at the veryfirst beginning of your Header oder .m file, its also likely that this error accures.
^//
// EMServices.m
// MyController
//
// Created by EMart on 09.01.14.
// Copyright (c) 2014 EMart. All rights reserved.
//

Related

Why weak property of associated object is not nilled out if I call its getter?

Though it's kind of stupid in 2020 that I'm still asking question about ObjC, please be patient and considerate...
I'm reading the source code of BloksKit and ran into a weird situation.
#import <objc/runtime.h>
#interface _WeakAssociatedObjectWrapper : NSObject
#property (nonatomic, weak) id object;
#end
#implementation _WeakAssociatedObjectWrapper
#end
#interface NSObject (AddWeak)
#end
#implementation NSObject (AddWeak)
- (void)setWeakProp:(id)weakProp {
_WeakAssociatedObjectWrapper *wrapper = objc_getAssociatedObject(self, #selector(weakProp));
if (!wrapper) {
wrapper = [[_WeakAssociatedObjectWrapper alloc] init];
objc_setAssociatedObject(self, #selector(weakProp), wrapper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
wrapper.object = weakProp;
}
- (id)weakProp {
id value = objc_getAssociatedObject(self, _cmd);
if ([value isKindOfClass:_WeakAssociatedObjectWrapper.class]) {
return [(_WeakAssociatedObjectWrapper *)value object];
}
return value;
}
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSObject *obj = [[NSObject alloc] init];
{
NSObject *prop = [[NSObject alloc] init];
[obj setWeakProp:prop];
[obj weakProp]; // *Weird!!
}
NSLog(#"Now obj.weakProp = %#", [obj weakProp]);
}
return 0;
}
This code is adding a weak associated object for category.(BlocksKit does so)
Note the *Weird!! line. If this line is commented out, then it prints (null), which is reasonable since prop is deallocated outside the {} scope. On the other side, if not commented out, it prints <NSObject: 0xxxxx>, which indicates that prop is somehow retained by someone(Or any other reason?).
What is happening here??! (BlocksKit behaves the same!)
Environment: XCode 10.3
This is a feature. For the case (and any similar)
[obj weakProp];
by properties/accessors naming convention ARC returns autoreleased instance, so in your case #autoreleasepool holds it and testing as below can show this.
int main(int argc, const char * argv[]) {
NSObject *obj = [[NSObject alloc] init];
#autoreleasepool {
{
NSObject *prop = [[NSObject alloc] init];
[obj setWeakProp:prop];
[obj weakProp]; // *Weird!!
}
NSLog(#"Now obj.weakProp = %#", [obj weakProp]);
}
NSLog(#"After autoreleased >> obj.weakProp = %#", [obj weakProp]);
return 0;
}

How does the Xcode breakpoint system interact with memory management?

Here's a little experiment:
#interface Model : NSObject
#property (copy) NSString *value;
-(instancetype)initWith:(NSString *)value;
#end
#implementation Model
-(instancetype)initWith:(NSString *)value {
self = [super init];
self.value = value;
return self;
}
#end
#import <Foundation/Foundation.h>
#import "Model.h"
void experiment(Model *m);
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
NSLog(#"Hello, World!");
Model *ma = [[Model alloc] initWith:[[NSUUID UUID] UUIDString]];
experiment(ma);
NSLog(#"yyy %#", [ma value]);
}
return 0;
}
void experiment(ModelA *m) {
NSString *testValue = nil;
testValue = [m value];
NSLog(#"xxx %#", testValue);
}
When run, this produces the following:
Hello, World!
xxx 6005A7B0-F71C-4755-B1BF-792D6296B716
yyy 6005A7B0-F71C-4755-B1BF-792D6296B716
Program ended with exit code: 0
But suppose I make this line:
testValue = [m value];
part of a breakpoint:
And this changes everything:
Hello, World!
(__NSCFString *) $0 = 0x000000010071e220 #"1C0DCB39-BFBB-4E67-A041-E6B58615BDFD"
xxx 1C0DCB39-BFBB-4E67-A041-E6B58615BDFD
yyy 1C0DCB39-BFBB-4E67-A041-E6B58615BDFD
*** -[CFString release]: message sent to deallocated instance 0x10071e220
And a crash. I see what's happening--the string is released once we exit the function scope, and the second time when the Model object is destroyed, which is an overrelease. But why doesn't the breakpoint (or more precisely, the lldb expression inside the breakpoint) handle the reference count correctly?

How to use data from main.m in a subclass

I am doing homework from the Big Nerd Ranch Guide book. In the problem, I have two arrays in main.m. One is from a subclass and the other from a superclass. BNRItem is the superclass. BNRContainer is the subclass. In the implementation files I have description string which says what the NSLog should say. I need to take the data from the superclass used in main.m's array and use it in the subclass so that the subclass array can work. is there an easy answer?
In main.m I have the following:
// main.m
// RandomItems
#import <Foundation/Foundation.h>
#import "BNRItem.h"
#import "BNRContainer.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSMutableArray *items = [[NSMutableArray alloc] init];
for (int i = 0; i < 3; i++) {
BNRItem *item = [BNRItem randomItem];
[items addObject:item];
}
for (BNRItem *item in items) {
NSLog(#"%#", item);
}
NSMutableArray *containers = [[NSMutableArray alloc] init];
for (int i = 0; i < 3; i++) {
BNRContainer *container = [BNRContainer randomContainer];
[containers addObject:container];
}
for (BNRContainer *container in containers) {
NSLog(#"%#", container);
}
items = nil;
containers = nil;
}
return 0;
}
In BNRItem.h:
// BNRItem.h
// RandomItems
//
// Created by Meghan on 3/19/14.
// Copyright (c) 2014 Meghan. All rights reserved.
//
#import <Foundation/Foundation.h>
#interface BNRItem : NSObject
{
NSString *_itemName;
NSString *_serialNumber;
int _valueInDollars;
NSDate *_dateCreated;
}
+ (instancetype)randomItem;
//Designated initializer for BNRItem
- (instancetype)initWithItemName:(NSString *)name
valueInDollars:(int)value
serialNumber:(NSString *)sNumber;
-(instancetype)initWithItemName:(NSString *)name;
- (NSString *)description;
- (void)setItemName:(NSString *)str;
-( NSString *)itemName;
- (void)setSerialNumber:(NSString *)str;
- (NSString *)serialNumber;
- (void)setValueInDollars:(int)v;
- (int)valueInDollars;
- (NSDate *)dateCreated;
#end
in BNRContainer.h:
// BNRContainer.h
// RandomItems
//
// Created by Meghan on 3/20/14.
// Copyright (c) 2014 Meghan. All rights reserved.
//
#import "BNRItem.h"
#interface BNRContainer : BNRItem
{
NSString *_containerName;
int _containerItemsSum;
int _containerValue;
int _totalContainerValue;
}
- (NSString *)description;
+ (instancetype)randomContainer;
//Designated initializer for BNRContainer
- (instancetype)initWithContainerName:(NSString *)name
containerItemsSum:(int)iSum
containerValue:(int)value
totalContainerValue:(int)tvalue;
- (instancetype)initWithContainerName:(NSString *)name;
- (instancetype)init;
- (void)setContainerName:(NSString *)str;
- (NSString *)containerName;
- (void)setContainerItemsSum:(int)v;
- (int)containerItemsSum;
- (void)setContainerValue:(int)v;
- (int)containerValue;
- (void)setTotalContainerValue:(int)v;
- (int)totalContainerValue;
#end
The variable containerItemsSum in BNRContainer should be the sum of valueInDollars of several items and the value is generated in main.m when it is looped through.
// BNRItem.m
// RandomItems
//
// Created by Meghan on 3/19/14.
// Copyright (c) 2014 Meghan. All rights reserved.
//
#import "BNRItem.h"
#implementation BNRItem
- (instancetype)initWithItemName:(NSString *)name
valueInDollars:(int)value
serialNumber:(NSString *)sNumber
{
self = [super init];
if (self) {
//Give the instance variables initial values
_itemName = name;
_serialNumber = sNumber;
_valueInDollars = value;
//Set dateCreated to the current date and time
_dateCreated = [[NSDate alloc]init];
}
return self;
}
-(instancetype)initWithItemName:(NSString *)name
{
return [self initWithItemName:name
valueInDollars:0
serialNumber:#""];
}
- (instancetype)init
{
return [self initWithItemName:#"Item"];
}
+ (instancetype)randomItem
{
NSArray *randomAdjectiveList = #[#"Fluffy", #"Rusty", #"Shiny"];
NSArray *randomNounList = #[#"Bear", #"Spork", #"Mac"];
NSInteger adjectiveIndex = arc4random() % [randomAdjectiveList count];
NSInteger nounIndex = arc4random() % [randomNounList count];
NSString *randomName = [NSString stringWithFormat:#"%# %#",
randomAdjectiveList[adjectiveIndex],
randomNounList[nounIndex]];
int randomValue = arc4random() % 100;
NSString *randomSerialNumber = [NSString stringWithFormat:#"%c%c%c%c%c",
'0' + arc4random() % 10,
'A' + arc4random() % 26,
'0' + arc4random() % 10,
'A' + arc4random() % 26,
'0' + arc4random() % 10];
BNRItem *newItem = [[self alloc] initWithItemName:randomName
valueInDollars:randomValue
serialNumber:randomSerialNumber];
return newItem;
}
- (void)setItemName:(NSString *)str
{
_itemName = str;
}
- (NSString *)itemName
{
return _itemName;
}
- (void)setSerialNumber:(NSString *)str
{
_serialNumber = str;
}
- (NSString *)serialNumber
{
return _serialNumber;
}
- (void)setValueInDollars:(int)v
{
_valueInDollars = v;
}
- (int)valueInDollars
{
return _valueInDollars;
}
- (NSDate *)dateCreated
{
return _dateCreated;
}
- (NSString *)description
{
NSString *descriptionString =
[[NSString alloc] initWithFormat:#"%# (%#): Worth $%d, recorded on %#",
self.itemName,
self.serialNumber,
self.valueInDollars,
self.dateCreated];
return descriptionString;
}
#end
for (BNRItem *item in items) {
NSLog(#"%#", item);
}
Here, you're passing through each BNRItem that you've created. This is your opportunity to collect information about the items.
Create a local variable to store the total, and add to it each item you read:
int dollarTotal = 0;
for (BNRItem *item in items) {
NSLog(#"%#", item);
dollarTotal += [item valueInDollars];
}
NSLog(#"Total value in dollars is %d",dollarTotal);
You'd then use this value to set the total for the container, although this seems completely backward. A BNRContainer should (though this may be a later point in the tutorial you are doing) be able to derive this total from its own set of contained items, using a loop similar to the one above. I don't see why you are creating three containers in a loop either. The example doesn't make a great deal of sense.

How to return an NSString * in Objective C (keep getting invalid summary)

So I presume this is a memory issue, here's the code:
- (NSString *)giveMeAStringGoddammit
{
NSString *s;
// switch statement to choose which string to assign to s, so essentially:
s = #"a string";
return s;
}
And the calling code:
NSString *aString;
aString = [self giveMeAStringGoddammit];
However after this call, aString has an invalid summary when debugged and crashes when run.
I suspect I'm missing a retain or something, can someone help? Thanks.
What you've got works just fine:
#import <Foundation/Foundation.h>
#interface Test : NSObject
- (NSString *)giveMeAStringGoddammit;
#end
#implementation Test
- (NSString *)giveMeAStringGoddammit
{
NSString *s;
// switch statement to choose which string to assign to s, so essentially:
s = #"a string";
return s;
}
#end
int main (int argc, const char * argv[])
{
#autoreleasepool {
Test *t = [[Test alloc] init];
NSLog(#"t says: %#", [t giveMeAStringGoddammit]);
}
return 0;
}
The output of this program is:
t says: a string
To make this a little more realistic, let's change it to use a property:
#import <Foundation/Foundation.h>
#interface Test : NSObject
#property(copy, nonatomic) NSString *string;
- (NSString *)giveMeAStringGoddammit;
#end
#implementation Test
#synthesize string;
- (NSString *)giveMeAStringGoddammit
{
NSString *s;
// switch statement to choose which string to assign to s, so essentially:
s = self.string;
return s;
}
#end
int main (int argc, const char * argv[])
{
#autoreleasepool {
Test *t = [[Test alloc] init];
t.string = #"Hello world!";
NSLog(#"t says: %#", [t giveMeAStringGoddammit]);
}
return 0;
}
This does what you'd expect:
t says: Hello world!
You have created a pointer object and it's expected to increment it's retain count whenever you referring them, for increasing retain count the string should be initiated and allocated with memory else you could use [NSString stringwithString:[self giveMeAStringGoddammit]. You can use this definition only when you exactly need it reference locally. because whenever you try to refer it out side the auto release pool will crash the app (hence it's not retained manually). So if you need to use it out side of the function, better use [NSString alloc]init] and then load your string to the pointer object. Well the way to make your code to work is add the lines NSString *aString = [NSString stringWithString:[self giveMeAStringGoddammit]];
NSLog(#"My Str:%#",aString); Hooray now the goddammit string was given......

I am trying to use respondsToSelector but unable to get expected output can anyone find what is wrong in my code?

#import "movie.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
movie *obj = [[movie alloc]init];
[obj findinterestofnum1:(int)200 num2:(int)4 num3:(int)5];
SEL suf = #selector(findinterestofnum1: num2:num3:);
BOOL sul = [obj respondsToSelector:suf];
if(sul)
{
NSLog(#"It is implememted");
}
else
{
NSLog(#" It is not implemented");
}
NSLog(#"Hello, World!");
[pool drain];
return 0;
}
********-----
#interface movie : NSObject {
#private
}
-(void)findinterestofnum1:(int)p num2:(int)n num3:(int)r;
#end
*******-------
#import "movie.h"
#implementation movie
-(void)findinterestofnum1:(int)p num2:(int)n num3:(int)r
{
int a ;
a= (p*n*r/100);
NSLog(#"interest value is =%d",a);
}
- (void)dealloc
{
[super dealloc];
}
#end
i am trying to find whether method is implemented and if it is not it should print it is not implemented
#toddler, respondsToSelector just checks if the corresponding object can respond to that particular method. It doesn't do any checks on whether interface has that definition associated with it since it is a runtime check.
If you had removed the code from the implementation file (.m file) and not the interface, you would have got an error while executing it and you would have found that the BOOL sul is FALSE.