Xcode telling me that I have an "Incomplete implementation" - objective-c

My teacher has given me this main.m that I must code the .h and .m methods for. In my .m(not main) file I made I am getting an "Incomplete implementation" warning from Xcode. I have made methods for all that were called so I can't figure out why it is saying that. Here is the code given to us that I cannot modify:
#import <Foundation/Foundation.h>
#import "ChutesAndLadders.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
ChutesAndLadders *cl = [[ChutesAndLadders alloc]init];
[cl initBoard];
[cl makeChutes:10];
[cl makeLadders:10]
int chutes=0;
int ladders=0;
for(int i=0;i<cl.board.count;i++){
NSString * cell = (NSString *)[cl.board objectAtIndex:i];
int additionalSpaces = (int)[cl addToMove:cell];
if(additionalSpaces>0)
ladders++;
else if (additionalSpaces<0)
chutes++;
}
[cl printBoard];
}
return 0;
}
Here is the .h that I coded, I believe it is OK:
#import <Foundation/Foundation.h>
#interface ChutesAndLadders : NSObject{
#private
NSMutableArray * board;
}
#property (readwrite, retain) NSMutableArray *board;
-(id) initBoard;
-(NSString *)addToMove: (NSString *) cell;
-(void)makeChutes: (int) length;
-(void)makeLadders: (int) length;
-(void)printBoard;
#end
Here is my .m which is where I'm having the problem at the "#implementation ChutesAndLadders" line:
#import "ChutesAndLadders.h"
#implementation ChutesAndLadders//incomplete impementation????????????
#synthesize board=_board;
-(void) initBoard{
//self = [super init];
//if (self){
_board = [board initWithCapacity: 100];
//self._board=[[NSMutableArray alloc]initWithCapacity:100];
for(int i =0; i < 100; i++){
[_board addObject:#""];
//}
}
}
-(void)makeChutes: (int) length {
//Make argument number of Chutes randomly across the board.
for(int i = 0; i < length;){
int random = arc4random_uniform(101);
if ([[_board objectAtIndex:random] isEqual:#""]) {
NSString *fString = [NSString stringWithFormat:#"C%d", length];
[_board replaceObjectAtIndex:random withObject:fString];
i++;
}
}
}
-(void)makeLadders: (int) length {
//Make argument number of Ladders randomly across the board.
for(int i = 0; i < length;){
int random = arc4random_uniform(101);
if ([[_board objectAtIndex:random] isEqual:#""]) {
NSString *fString = [NSString stringWithFormat:#"L%d", length];
[_board replaceObjectAtIndex:random withObject:fString];
i++;
}
}
}
-(NSString *)addToMove: (NSString*) cell {
if([[_board objectAtIndex:[cell integerValue]] isEqualToString:#"C10"]){
return (#"-10");
}
if([[_board objectAtIndex:[cell integerValue]] isEqualToString:#"L10"]){
return (#"10");
}
else
return (#"0");
}
-(void) printboard {
//Print the board in rows of 10 so that it looks like a square in console.
for(int i=0; i < (_board.count/10); i++){
for(int j = 0; j < 10; j++){
NSLog(#"|");
NSLog(#"%#", [_board objectAtIndex:(i+j)]);
NSLog(#"|");
}
NSLog(#"\n");
}
}
#end
This is my first assignment in Objective-C, Macs in general for that matter, and I've been at it for some time, mostly research/studing and I just can't see what I'm doing wrong.
I have not ran this program so sorry for any other stupid errors you may see, I will figure them out once I can actually get it to output to the console so I can see if it is doing what it is suppose to.

Open the Issue navigator via the triangle/exclamation mark button at upper-left:
If you expand your "Incomplete implementation" Semantic Issue with the little triangle at left, you can see the details of XCode's complaint.

The initBoard method has different return type in m file. Also, Objective-C is case sensitive. printBoard and printboard are not equal for obj-c compiler.
BTW. You should use init... name only for constructors. See Naming Methods doc from Apple.

In your .h file, there's a method named -(void)printBoard; But in your .m file, its name is -(void)printboard. Objective-C is case intensive.
And also, the -(id)initBoard; and -(void)initBoard.

You have defined addToMove and printBoard in the header file, but they are missing in the .m file. That is the reason for the warning.

Related

List of class properties in Objective-C

Is there a way to get an array of class properties of certain kind? For example if i have interface like this
#interface MyClass : NSObject
#property (strong,nonatomic) UILabel *firstLabel;
#property (strong,nonatomic) UILabel *secondLabel;
#end
can i get the reference to those labels in implementation without knowing their name?
#implementation MyClass
-(NSArray*)getListOfAllLabels
{
?????
}
#end
I know i can do it easily with [NSArray arrayWithObjects:firstLabel,secondLabel,nil], but i would like to do it with some kind of class enumeration like for (UILabel* oneLabel in ???[self objects]???)
So more precisely, you want dynamic, runtime observaion of the properties, if I got it correctly. Do something like this (implement this method on self, the class you want to introspect):
#import <objc/runtime.h>
- (NSArray *)allPropertyNames
{
unsigned count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
NSMutableArray *rv = [NSMutableArray array];
unsigned i;
for (i = 0; i < count; i++)
{
objc_property_t property = properties[i];
NSString *name = [NSString stringWithUTF8String:property_getName(property)];
[rv addObject:name];
}
free(properties);
return rv;
}
- (void *)pointerOfIvarForPropertyNamed:(NSString *)name
{
objc_property_t property = class_getProperty([self class], [name UTF8String]);
const char *attr = property_getAttributes(property);
const char *ivarName = strchr(attr, 'V') + 1;
Ivar ivar = object_getInstanceVariable(self, ivarName, NULL);
return (char *)self + ivar_getOffset(ivar);
}
Use it like this:
SomeType myProperty;
NSArray *properties = [self allPropertyNames];
NSString *firstPropertyName = [properties objectAtIndex:0];
void *propertyIvarAddress = [self getPointerOfIvarForPropertyNamed:firstPropertyName];
myProperty = *(SomeType *)propertyIvarAddress;
// Simpler alternative using KVC:
myProperty = [self valueForKey:firstPropertyName];
Hope this helps.
use attributeKeys method of NSObject.
for (NSString *key in [self attributeKeys]) {
id attribute = [self valueForKey:key];
if([attribute isKindOfClass:[UILabel class]])
{
//put attribute to your array
}
}
Check out this link. It is an objective c wrapper over objective C runtime.
You can use code like below
uint count;
objc_property_t* properties = class_copyPropertyList(self.class, &count);
NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count ; i++)
{
const char* propertyName = property_getName(properties[i]);
[propertyArray addObject:[NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding]];
}
free(properties);
You must include the runtime headers
#import<objc/runtime.h>
uint propertiesCount;
objc_property_t *classPropertiesArray = class_copyPropertyList([self class], &propertiesCount);
free(classPropertiesArray);
The answer by #user529758 won't work with ARC and it won't list the properties of any ancestor classes.
To fix this, you need to traverse up the class hierarchy, and use the ARC-compatible [NSObject valueForKey:] to get the property values.
Person.h:
#import <Foundation/Foundation.h>
extern NSMutableArray *propertyNamesOfClass(Class klass);
#interface Person : NSObject
#property (nonatomic) NSString *name;
#end
Person.m:
#import "Person.h"
#import <objc/runtime.h>
NSMutableArray *propertyNamesOfClass(Class klass) {
unsigned int count;
objc_property_t *properties = class_copyPropertyList(klass, &count);
NSMutableArray *rv = [NSMutableArray array];
for (unsigned int i = 0; i < count; i++)
{
objc_property_t property = properties[i];
NSString *name = [NSString stringWithUTF8String:property_getName(property)];
[rv addObject:name];
}
free(properties);
return rv;
}
#implementation Person
- (NSMutableArray *)allPropertyNames {
NSMutableArray *classes = [NSMutableArray array];
Class currentClass = [self class];
while (currentClass != nil && currentClass != [NSObject class]) {
[classes addObject:currentClass];
currentClass = class_getSuperclass(currentClass);
}
NSMutableArray *names = [NSMutableArray array];
[classes enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(Class currentClass, NSUInteger idx, BOOL *stop) {
[names addObjectsFromArray:propertyNamesOfClass(currentClass)];
}];
return names;
}
- (NSString*)description {
NSMutableArray *keys = [self allPropertyNames];
NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithCapacity:keys.count];
[keys enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop) {
properties[key] = [self valueForKey:key];
}];
NSString *className = NSStringFromClass([self class]);
return [NSString stringWithFormat:#"%# : %#", className, properties];
}
Student.h:
#import "Person.h"
#interface Student : Person
#property (nonatomic) NSString *studentID;
#end
Student.m:
#import "Student.h"
#implementation Student
#end
main.m:
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
Student *student = [[Student alloc] init];
student.name = #"John Doe";
student.studentID = #"123456789";
NSLog(#"student - %#", student);
}
return 0;
}
The solution of serhats is great unfortunately it doesn't work for iOS (as you mentioned) (and this question is tagged for iOS). A workaround would be to get a NSDictionary representation of the object and then access it normally as key-value pairs. I would recommend a category for NSObject:
Header-File:
#interface NSObject (NSDictionaryRepresentation)
/**
Returns an NSDictionary containing the properties of an object that are not nil.
*/
- (NSDictionary *)dictionaryRepresentation;
#end
Implementation-File:
#import "NSObject+NSDictionaryRepresentation.h"
#import <objc/runtime.h>
#implementation NSObject (NSDictionaryRepresentation)
- (NSDictionary *)dictionaryRepresentation {
unsigned int count = 0;
// Get a list of all properties in the class.
objc_property_t *properties = class_copyPropertyList([self class], &count);
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:count];
for (int i = 0; i < count; i++) {
NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])];
NSString *value = [self valueForKey:key];
// Only add to the NSDictionary if it's not nil.
if (value)
[dictionary setObject:value forKey:key];
}
free(properties);
return dictionary;
}
#end
Borrowed from this article: http://hesh.am/2013/01/transform-properties-of-an-nsobject-into-an-nsdictionary/
This way you could do something similar as serhats mentioned:
for (NSString *key in objectDic.allKeys) {
if([objectDic[key] isKindOfClass:[UILabel class]])
{
//put attribute to your array
}
}

"Missing context for method declaration" for overridden description method

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.
//

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.

Is there a way to dynamically determine ivars of a class at runtime in Cocoa / Cocoa Touch?

Is there a way to obtain something like a dictionary of all key-value pairs of a class?
You'd have to roll your own using the Objective-C Runtime functions. Here's some very basic sample code. Note that getting the ivars of a class doesn't get the ivars of its superclass. You'd need to do that explicitly, but the functions are all there in the runtime.
#import <objc/objc-runtime.h>
#include <inttypes.h>
#include <Foundation/Foundation.h>
#interface Foo : NSObject
{
int i1;
}
#end
#implementation Foo
#end
#interface Bar : Foo
{
NSString* s1;
}
#end
#implementation Bar
#end
int main(int argc, char** argv)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
unsigned int count;
Ivar* ivars = class_copyIvarList([Bar class], &count);
for(unsigned int i = 0; i < count; ++i)
{
NSLog(#"%#::%s", [Bar class], ivar_getName(ivars[i]));
}
free(ivars);
[pool release];
}
I'm not sure for just ivars but if you have them defined as properties it is possible to access the available properties on a class.
I've been using SQLitePersistentObjects for a couple projects and it has some helpful code that gets the properties defined on the class to use when figuring out serialization to and from sqlite.
It uses the function class_copyPropertyList to get the available list of properties on a class.
More specifically:
+(NSDictionary *)propertiesWithEncodedTypes
{
// DO NOT use a static variable to cache this, it will cause problem with subclasses of classes that are subclasses of SQLitePersistentObject
// Recurse up the classes, but stop at NSObject. Each class only reports its own properties, not those inherited from its superclass
NSMutableDictionary *theProps;
if ([self superclass] != [NSObject class])
theProps = (NSMutableDictionary *)[[self superclass] propertiesWithEncodedTypes];
else
theProps = [NSMutableDictionary dictionary];
unsigned int outCount;
objc_property_t *propList = class_copyPropertyList([self class], &outCount);
int i;
// Loop through properties and add declarations for the create
for (i=0; i < outCount; i++)
{
objc_property_t * oneProp = propList + i;
NSString *propName = [NSString stringWithUTF8String:property_getName(*oneProp)];
NSString *attrs = [NSString stringWithUTF8String: property_getAttributes(*oneProp)];
NSArray *attrParts = [attrs componentsSeparatedByString:#","];
if (attrParts != nil)
{
if ([attrParts count] > 0)
{
NSString *propType = [[attrParts objectAtIndex:0] substringFromIndex:1];
[theProps setObject:propType forKey:propName];
}
}
}
free(propList);
return theProps;
}
This returns a dictionary of the properties - you'll need to do some investigating of the results you get back but you should be able to get what you need if you're using properties.
Yep, totally possible:
int numIvars = 0;
Ivar * ivars = class_copyIvarList([anInstanceOfAClass class], &numIvars);
NSMutableDictionary * pairs = [NSMutableDictionary dictionary];
for (int i = 0; i < numIvars; ++i) {
Ivar ivar = ivars[i];
NSString * ivarName = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding];
id ivarValue = [anInstanceOfAClass valueForKey:ivarName];
[pairs setObject:ivarValue forKey:ivarName];
}
free(ivars);
NSLog(#"%#", pairs);