cocoa -[Person copyWithZone:]: unrecognized selector sent to instance - objective-c

I'm doing some cocoa programming follows the Cocoa programming for Mac OS X, I'm trapped in Chapter 8(NSArrayController), I'm following the guide defined in that book, but I don't know why the app always raising unrecognized selector sent to instance error.
My code is here RaiseMan, If you have any suggestion, Thanks very much.

I've fixed it myself. The behaviour of NSArrayController add method is to copy an object, not holding the pointer of the object, What I've encountered is I haven't implement NSCoping protocol in class Person, I fixed it like this:
in Person.h declar NSCoping:
#interface Person : NSObject <NSCopying> {
NSString *personName;
float expectedRaise;
}
and in Person.m implement it:
-(id)copyWithZone:(NSZone *)zone
{
return self;
}

Related

Problems passing and using selectors when making buttons

I am trying to do some coding in Xcode and am having some problems with selectors. I have created a subclass of NSButton called modifiedNSButton. One of the constructors is
+ (id)CreateButtonViewUsingObject:(id)targetObject selector:(SEL)select caption:(NSString *)label;
However, the only way I have been able to get it to work is to pass the selector as #selector(bleep:) It works but I get the message
Incompatible pointer types sending 'NSString *' to parameter of type 'SEL'
I assume that this means that #selector(bleep:) is sent as an NSString instead of a SEL. However, it seems to work and I can't tell if I am doing something wrong. I will post my code to my Git for people to look at and then give a pointer to the location.
First, you really should follow the naming conventions in Objective C:
your Class should be named ModifiedNSButton, starting with a big letter
in contrary, functions should start with a small letter
Then, a "constructor" should also follow some conventions:
The return type should be instancetype, not id
If it's an initializer, start with init... (like initUsingObject...)
If it's a class factory, start the function with the name of the class.
In your case, you should name it
+ (instancetype) modifiedNSButtonUsingObject:(id)targetObject selector:(SEL)select caption:(NSString*)label
After all this said, I don't see a problem with your code:
#interface ModifiedNSButton : NSButton
#end
#implementation ModifiedNSButton
+ (instancetype)modifiedNSButtonUsingObject:(id)targetObject selector:(SEL)select caption:(NSString *)label {
return [self new];
}
- (void) handler {
}
- (void) handlerWithName:(NSString*)name andValue:(NSInteger)value {
}
- (void) test {
NSButton *b1 = [ModifiedNSButton modifiedNSButtonUsingObject:self selector:#selector(handler) caption:#"One"];
NSButton *b2 = [ModifiedNSButton modifiedNSButtonUsingObject:self selector:#selector(handlerWithName:andValue:) caption:#"Two"];
}
#end
I don't see any "incompatible pointer type" warnings.

Ambiguous reference to member 'delegate'

I'm trying to create an instance of a singleton class written in Objective-C. I must conform to it's delegate protocol. The Swift implementation looks something like this:
class SomeClass: ManagerDelegate {
let manager = Manager.sharedInstance()
func someFunction(){
manager.delegate = self
}
}
The Objective-C singleton class looks something like this:
// header
#protocol ManagerDelegate <NSObject>
#required
-(void)delegateMethod;
#end
#interface Manager : NSObject {
}
+ (id)sharedInstance;
#property (nonatomic, assign) id delegate;
#end
// class file
+ (id) sharedManager{
static Manager *theSharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
theSharedManager = [[self alloc] init];
});
return theSharedManager;
}
- (void) someInternalMethod{
[delegate delegateMethod];
}
Upon specifying the delegate (manager.delegate = self), I receive the error
Ambiguous reference to member 'delegate'
Is the Objective-C class improperly formed or am I implementing it incorrectly? Am I missing something else?
Your problem is caused by the definition of your sharedInstance method in Objective-C. By declaring it as
+ (id)sharedInstance;
it gets converted to sharedInstance() -> AnyObject! in Swift. Swift then doesn't know which of many potential delegate properties that it can find you mean. If you change your Objective C declaration and implementation to be:
+ (instancetype)sharedInstance;
your problem will go away.
And as #rmaddy points out, your delegate should be weak not assign. If you use assign then delegate will be left as an invalid pointer in the event that the delegate is deallocated.
Also, the use of a delegate with a singleton is a bit contradictory. Given that you will only ever have one instance of the Manager which may be used by a number of other objects and you can only have one active delegate at a time there is the potential for conflicts.
I would suggest that either blocks/closures or NSNotification is a better approach to call backs from a singleton.
Its because whenever you bring instance from objective c code to swift it gives as AnyObject so
let manager = Manager.sharedInstance() //manager is AnyObject due to bridging between objc and swift
gives you AnyObject for manager property. You need to forcefully cast that AnyObject to Manager to use it as manager's instance like below.
class SomeClass: NSObject, ManagerDelegate {
let manager = Manager.sharedInstance() as! Manager //here was your error
func someFunction(){
manager.delegate = self
}
func delegateMethod() {
print("Hello")
}
}
Hope this solves your problem :)

NSObject call to self gives XCode error

I have a class WebServices that inherits from NSObject. I am using xcode4.2 and ARC turned on.
When I created the class, there was no other method in the NSObject lie viewDidLoad or init.
The issues is that when I try to call self.something or [self someMethod] Xcode flags my code red and complains with:
implicit conversion of Objective-C pointer type 'Class' to C pointer type 'struct obj_class*' requires a bridge cast
Please help. Why isn't cocoa like java where you call "this" and get the object you are in?
// WebService.h file
#interface WebService : NSObject
#property (weak, nonatomic) NSString * myString;
+(void) setAndPrintMyString:(NSString*) someString;
#end
//WebService.m file
#import "WebService.h"
#implementation WebService
#synthesize myString=_myString;
+(void) printMyString:(NSString*) someString{
[self setMyString:someString]; //XCode does not allow
NSLog(#"myString is set to %#",self.myString); //XCode dose not allow
}
#end
Declaring a method with + means that it is a class method. Within a class method self refers to the class itself, which in your case would be [WebService class]. If you declared and instance method (using -) then inside the method self would refer to the instance, which is what you want.
To set an instance variable - you need an instance
WebService *webService = [[WebService alloc] init];
webService.myString = #"some string";
Now to make your method work you need to declare it with a - instead of + which makes it an instance method
- (void)printMyString:(NSString *)someString
{
[self setMyString:someString];
NSLog(#"myString is set to %#",self.myString);
}
Now
[webService printMyString:#"boom"];
results in the instance variable myString being set to boom and the console logging out `myString is set to boom".
viewDidLoad method doesn't fit with NSObject subclass. It's a method for UI which will be there in UIViewController subclasses.
Now, Coming to point about self.something OR [self someMethod], That works perfectly well with NSObject subclasses. You need to show us the code, in which you are facing problem.
Just for your reference (I think you should start developing for iOS after going through this):
NSObject Class Reference
UIViewController Class Reference

Why does xcode find interface for some methods but not others?

I have a header file for an object as follows.
#import <Foundation/Foundation.h>
#interface CSSRuleSet : NSObject{
NSMutableArray *Selectors;
NSArray *Properties;
NSMutableArray *Values;
}
-(void)printElement;
-(void)initialiseArrays;
-(NSString *)getValue:(NSString *)Property;
-(void)assignValue:(NSString *)Property:(NSString *)Value;
-(void)addSelector:(NSString *)Selector;
#end
However, when I try to call methods on that object, some work, others throw up an error "no visible #interface for 'CSSStore' declares the selector 'initialiseArrays'".
The ones I am having problems with are printElement and initialiseArrays. For some reason I couldn't write a custom init function for this object either: it was there and didn't throw up any errors, it just wouldn't run.
Let me know if more information is needed. Thanks in advance!
This class is CSSRuleSet. You appear to be trying to send messages intended for this class to a different class called CSSStore. The most likely reasons would be that either you've lost track of what object you're passing around at some point or you're not managing retains and releases correctly in a non-ARC program.

How to implement a custom protocol

In this part of my code I get a warning message saying it doesn't implement the custom protocol I made.
detailViewController.delegate = self;
How do I implement the protocol?
Then when I run the program it crashes saying
'-[DetailViewController setDelegate:]: unrecognized selector sent to instance 0x6a1c450'
Declare your class like this:
#interface DetailViewController : UIViewController <MyProtocol> {
// Class stuff
}