explain how description method works in NSObject class - objective-c

In NSObject.h header file, i have seen a method
+ (NSString *)description;
I knew that "+" sign before the method indicates that it is a class method
Here is my entire program
#import <Foundation/Foundation.h>
#interface A : NSObject
#end
#implementation A
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
A * aObj = [A new];
NSLog(#"%#",[A description]);//o/p: A
NSLog(#"%#",[aObj description]);//o/p: <A: 0x10010f5a0>
}
return 0;
}
I have used the description method with both class as well with instance of it and i got the o/p as well. why i have not received any error or warning while using a class method using an instance particularly in this case
[aObj description];//why this piece of code is working fine
Thank you in Advance

Because NSObject has two methods:
+ (NSString *)description; // Class method
- (NSString *)description; // Instance method
So when you do [A description] you're calling the class method (declared in NSObject Class), when you do [aObj description] you're calling the instance method (declared in NSObject Protocol).

Related

Class creation unrecognized selector

I'm learning Objective-C.
I'm at the point of creating a simple class but when compiling, after the expected result, I get this errors.
2014-05-08 10:15:47.998 ClassCreation[978:903] This is a method call in the new object!
2014-05-08 10:15:48.007 ClassCreation[978:903] -[Employee setName:]: unrecognized selector sent to instance 0x10010c850
...
terminate called after throwing an instance of 'NSException'
(gdb)
Here it is the Employee.h
#import <Foundation/Foundation.h>
#interface Employee : NSObject
// properties
#property NSString *name;
#property NSDate *hireDate;
#property int employeeNumber;
-(void) someMethod;
#end
Here it is the Employee.m
#import "Employee.h"
#implementation Employee
// matching the method definition that is defined in the interface
-(void) someMethod {
NSLog(#"This is a method call in the new object!");
}
#end
Here it is the main.m
#import <Foundation/Foundation.h>
#import "Employee.h"
int main (int argc, const char * argv[])
{
#autoreleasepool {
// inside here, I instantiate a new object of my new employee class
Employee *fred = [[Employee alloc] init];
// call a method of our new object
[fred someMethod];
// change a property of new object
[fred setName:#"Fred Smith"];
}
return 0;
}
I'm on 10.6.8 with Xcode 4.2
With XCode 4.2 you need to add the line
#synthesize name,hireDate,employeeNumber;
to your Employee.m file after the #implementation line
Auto synthesis of properties only became available with XCode 4.4 - http://useyourloaf.com/blog/2012/08/01/property-synthesis-with-xcode-4-dot-4.html
You should look at upgrading your XCode version

Problems with subclasses inheriting class factory methods (Objective-C)

While I'm more than familiar with C#, I'm totally new at Objective C and iOS development. So I'm learning the language. What I don't understand is why the following code throws a compiler error (and yes, this is from the exercises at Programming with Objective C:
SNDPerson:
#interface SNDPerson : NSObject
#property NSString *first;
#property NSString *last;
+ (SNDPerson *)person;
#end
#implementation SNDPerson
+ (SNDPerson *)person
{
SNDPerson *retVal = [[self alloc] init];
retVal.first = #"Ari";
retVal.last = #"Roth";
return retVal;
}
#end
SNDShoutingPerson:
#import "SNDPerson.h"
#interface SNDShoutingPerson : SNDPerson
#end
#implementation SNDShoutingPerson
// Implementation is irrelevant here; all it does is override a method that prints a string
// in all caps. This works; I've tested it. However, if necessary I can provide more code.
// The goal here was for a concise repro.
#end
Main method:
- int main(int argc, const char * argv[])
{
SNDShoutingPerson *person = [[SNDShoutingPerson alloc] person]; // Error
...
}
The error is "No visible #interface for "SNDShoutingPerson" declares the selector "person".
Shouldn't this work? SNDShoutingPerson inherits from SNDPerson, so I would have assumed it got access to SNDPerson's class factory methods. Did I do something wrong here, or do I have to declare the method on SNDShoutingPerson's interface as well? The exercise text implies that what I did should Just Work.
Omit the +alloc when calling the class method:
SNDShoutingPerson *person = [SNDShoutingPerson person];
Briefly:
+ (id)foo denotes a class method. This takes the form:
[MONObject method];
- (id)foo denotes an instance method. This takes the form:
MONObject * object = ...; // << instance required
[object method];
Also, you can declare + (instancetype)person in this case, rather than + (SNDPerson *)person;.
change the line SNDShoutingPerson *person = [[SNDShoutingPerson alloc] person]; // Error
to
SNDShoutingPerson *person = [[SNDShoutingPerson alloc] init];
Cheers.
If you want to call class method:
SNDPerson person = [SNDPerson person];
person is a class method, but you're trying to call it with the incompletely constructed instance returned by alloc. Kill the alloc and just do [SNDShoutingPerson person].
This has nothing to do with subclasses, by the way. You would get the same error if you had written [[SNDPerson alloc] person].

Why I cannot do self.strID=nil;?

self.strID=nil;
It pops error saying:
reason: '-[BGFacebookHandler setStrID:]: unrecognized selector sent to instance 0x20525240'
* First throw call stack:
However, I declared the property as read write privately:
#property (nonatomic) NSString * strID;
The catch is it's also declared as read only publicly through protocol. Basically I am implementing that public property with a private property.
What's wrong with my approach?
Obviously I can do #synthesize, but doing so means using obsolete version of objective-c
This is a run time error. Not a compile error. The code compile just fine by the way.
Declaring your implementation property as part of your interface or a private extension changes nothing at runtime. There must me something else missing in your code because I have the following code fragment that works fine:
#protocol Facebook<NSObject>
- (NSString*) strID;
#end
#interface BGFacebookHandler : NSObject<Facebook>
#property (retain) NSString * strID;
#end
#implementation BGFacebookHandler
#end
int main (int argc, const char * argv[])
{
#autoreleasepool {
BGFacebookHandler *object = [[BGFacebookHandler alloc] init];
object.strID = #"Hello";
NSLog(#"strID = %#",object.strID);
}
return 0;
}

subclassing issue with static constant variable in iOS

I have Class A and Class B.
Class B subclasses Class A
Class A has a static constant NSString variable
In a method of Class B I need to use the static constant NSString variable of Class A. What are my options ?
I tried declaring the same thing again, but caused problem (internal inconsistency), tried without using (says, variable undeclared).
Any idea how I can solve this problem ?
Thanks.
Make a class method returning that constant, like this:
+(NSString*) constString {
return myConstString;
}
You can declare static constant strings in the .h file. That way they are public and can be used by other classes that import the header file, including your subclass.
Alternatively, you can declare a reference to the string in your Class B using extern:
extern NSString *const MyString;
That basically tells the compiler that the value of that string is defined elsewhere in the code and it doesn't have to worry about it.
By "Class A has a static constant NSString variable", I assume you're referring to having something like the following defined in your Class A .m file:
static NSString * const MyString = #"MyString";
#implementation ClassA
#end
To allow Class A and its subclasses to see the value, you can do something like this:
MDClassAPrivate.h:
#import <Foundation/Foundation.h>
static NSString * const MDBlahBlahKey = #"MDBlahBlah";
MDClassA.h:
#import <Foundation/Foundation.h>
#interface MDClassA : NSObject {
}
#end
MDClassA.m:
#import "MDClassA.h"
#import "MDClassAPrivate.h"
#implementation MDClassA
#end
MDClassB.h:
#import "MDClassA.h"
#interface MDClassB : MDClassA {
}
#end
MDClassB.m:
#import "MDClassB.h"
#import "MDClassAPrivate.h"
#implementation MDClassB
#end
By moving the static const variables to a separate file, you can allow any class to import them in the implementation file.
My personal solution to this problem would be a pseudo-protected method that returns the constant string.
// ClassA.m
#interface ClassA ()
- (NSString *)constantString;
#end
#implementation ClassA
- (NSString *)constantString {
return #"MyConstantString";
}
#end
Then following on into your subclass:
// ClassB.m
#interface ClassA ()
// This is a method redeclaration to avoid build warnings
- (NSString *)constantString;
#end
#implementation ClassB
- (void)someMethod {
NSString *theConstantString = [self constantString];
// do stuff...
}
#end
The assumption here is that your constant string really is constant, if you want it to be dynamic you would need to modify this solution slightly, but it can still handle it.
You can use 'userDefaults' to set a value that is accessible in the whole application.
[[NSUserDefaults standardUserDefaults] setObject:object forKey:#"objectKey"];

Is it possible to declare an Objective-C method outside a class?

I know that you can declare a C function outside of a class, but is it possible to declare a Objective-C method outside of a class?
Example:
// Works
void printHelloC()
{
NSLog(#"Hello.");
}
// Error
-(void) printHelloOC
{
NSLog(#"Hello.");
}
int main (int argc, const char * argv[])
{
#autoreleasepool {
printHelloC();
[self printHelloOC];// 'self' obviously would not work but you get the idea
}
return 0;
}
It depends. You can do something similar with method adding at runtime:
#import <objc/runtime.h>
void myCustomMethod(id self, SEL _cmd, id arg1, id arg2)
{
NSLog(#"This is a test, arg1: %#, arg2: %#", arg1, arg2);
}
int main(int argc, char *argv[])
{
Class NSObjClass = [NSObject class];
class_addMethod(NSObjClass, #selector(myNewMethod::), (IMP) myCustomMethod, "v#:##");
NSObject myObject = [NSObject new];
[myObject myNewMethod:#"Hi" :#"There"];
[myObject release];
return 0;
}
But that is about it outside of a #class construct, and it really just covers up what happens with a category.
You can use a category for this.
As an instance method:
#interface NSObject (MONStuff)
- (void)printHelloOC;
#end
#implementation NSObject (MONStuff)
- (void)printHelloOC
{
NSLog(#"Hello.");
}
#end
// in use:
NSObject * obj = ...;
[obj printHelloOC];
As a Class method:
#interface NSObject (MONStuff)
+ (void)printHelloOC;
#end
#implementation NSObject (MONStuff)
+ (void)printHelloOC
{
NSLog(#"Hello.");
}
#end
// in use:
[NSObject printHelloOC];
Of course, you must associate that with a class - so it's not exactly the same as you posted, but it's a close definition + declaration separate from the formal class declaration.
A method without an associated class is a meaningless concept. Functions, as you've noted, are just fine.
No, it is not possible - you will need to either use global C functions or class (+) methods.
Objective c functions are always associated with a class. If you mean you want to use an objective-c function without instantiating a class, you can of course write a class method (notice the plus sign instead of the usual hyphen)
#interface Test
+ (void)aClassMethod;
#end
then you can call it by calling
[Test aClassMethod];