I have a problem with an Objective-C class, when ARC is enabled.
My classes looks like these:
#interface ParentClass : NSObject {
}
-(void)decodeMethod;
#end
#implementation ParentClass
-(void)decodeMethod{
}
#end
#interface ChilldClass : ParentClass{
int *buffer;
}
#end
#implementation ChildClass
-(id)init{
self = [super init];
if(self != nil){
buffer = (int *)malloc(20*sizeof(int));
}
return self;
}
-(void)dealloc{
free(buffer);
}
#end
I have another class like this one:
#interface OtherClass : NSObject{
ParentClass *c;
}
#end
#implementation OtherClass
[...]
-(void)decode{
c = [[ChildClass alloc] init];
[c decodeMethod];
}
[...]
#end
As you can see, a ChildClass object is created and stored as an attribute in OtherClass. As long as the OtherClass object is living, the ChildClass object pointed by c should be also living, isn't it? Well, I have a BAD_ACCESS error, because after the ChildClass initialization, and before the decodeMethod is called, the dealloc method in ChildClass is automatically executed.
Why? ARC is enabled, so the dealloc method should be called automatically when the ChildClass object is released, but it shouldn't happen in this moment, because is still pointed with c.
Any help?
Thank you very much!
#interface ChilldClass : ParentClass{
It's possible your issue is caused by a spelling error in ChilldClass (typo?)
Related
As topic as topic. That problem exists from class ObjectSubA, i can't call method of object ObjectX. At one condition methods must have same name of method.
file.h
#interface ObjectX : NSObject
- (void) insert;
#end
#interface ObjectSubA : ObjectX
- (void) insert;
#end
#interface ObjectSubB : ObjectX
#end
file.m
#implementation ObjectX
- (void) insert{
NSLog(#"answer");
}
#end
#implementation ObjectSubA
-(void)insert{
NSLog(#"nothing")
[self insert]; // <- need answer, should call insert from ObjectX
}
#end
#implementation ObjectSubB
#end
#implementation app
-(void)launch{
ObjectSubA * a = [[ObjectSubA alloc]init];
[a insert]; // ObjectSubA -> method insert -> ObjectX -> insert -> end. #ERROR
ObjectSubB * b = [[ObjectSubB alloc] init];
[b insert]; //ObjectX -> insert -> end. OK
}
#end
just call super
- (void)insert{
NSLog(#"nothing");
[super insert];
}
From the Objective-C documentation
Objects Can Call Methods Implemented by Their Superclasses
There’s another important keyword available to you in Objective-C, called super. Sending a message to super is a way to call through to a method implementation defined by a superclass further up the inheritance chain. The most common use of super is when overriding a method.
I'm building a Static Library for iOS and I'd like to have some methods accessible to all the classes in the library, but not outside the library. Let's make an example:
This is a class called A with two methods available outside the library:
#interface A : NSObject
-(void)methoAvailableOutside1;
-(void)methoAvailableOutside2;
//This method has to be visible only to classes within the library
-(void)methodInternalToTheLibrary;
#end
The class called B is still internal to the library. It can call all methods belonging to A (also the method that should be "internal"):
#import "A.h"
#interface B : NSObject
#property A* aObject;
#end
This is the implementation of B:
#import "B.h"
#implementation B
-(instancetype)init{
self = [super init];
if(self){
_aObject = [[A alloc]init];
[_aObject methoAvailableOutside1];
[_aObject methoAvailableOutside2];
//here I can call the "internal" method
[_aObject methodInternalToTheLibrary];
}
return self;
}
#end
Now let's write an EXTERNAL class (external to the library, clearly):
#import "MyCustomLibrary.h"
#interface ExternalClass : NSObject
#property A* aObject;
#end
This is the implementation of the external class:
#import "ExternalClass.h"
#implementation ExternalClass
- (instancetype)init
{
self = [super init];
if (self) {
_aObject = [[A alloc]init];
[_aObject methoAvailableOutside1];
[_aObject methoAvailableOutside2];
//!!!Here THIS SHOULD BE...
[_aObject methodInternalToTheLibrary];
//...FORBIDDEN!!!
}
return self;
}
#end
How can I achieve this? Thank you in advance.
The only way I can think of is to have an additional header file with the additional method defined in that header. Anonymous categories.
publicHeader.h
#interface A : NSObject
-(void)methoAvailableOutside1;
-(void)methoAvailableOutside2;
#end
And then a mother .h file only used inside your library code.
privateHeader.h
#interface A()
//This method has to be visible only to classes within the library
-(void)methodInternalToTheLibrary;
#end
Could that work? It won't guarantee that other code can't call the method but the intention would be clear.
I have two classes:
Base class is player it has property name
Sub class is computer
How can I set the name of the computer player by accessing the base class property?
base class
#interface Player : NSObject
#property (nonatomic) NSString* playerName;
#property (nonatomic) int score;
-(id) initWithName :(NSString*) playerName;
-(void) addScore:(int) points;
#end
subclass
#interface Computer : Player
#end
.m
#import "Computer.h"
#implementation Computer
-(id)initWithName:(NSString *)name{
self = [super init];
}
#end
Your question is difficult to make out so please let me know if I've answered something other than what you are asking.
Assuming you have a class, car, that has inherited from a super class, vehicle, and that vehicle has an attribute, wheels, you can get at that in this way:
super.wheels = 4;
Call the property in the Computer Class like
super.name = #"Bob";
You can also call the methods of the superClass with
super.myMethod();
You can access the property from the superclass in the subclass directly.
Player.h
#interface Player : NSObject
#property(nonatomic, copy) NSString *name;
- (instancetype)initWithName:(NSString *)name;
#end
Computer.h
#interface Computer : Player
#end
Computer.m
#implementation Computer
- (instancetype)initWithName:(NSString *)name {
self = [super initWithName:name];
if (self) {
self.name = #"test";
}
return self;
}
#end
Although, as #Phillip Mills suggested, it's probably better practice to set the name property in Player.m instead.
can't understand what's wrong in this case, so I cant use the delegate - there is an exception in self.plistManager.delegate = self; Property 'delegate' not found on object of type 'DataPlistManager *'
#import "DataManager.h"
#import "DataPlistManager.h"
#interface DataAdapter : NSObject <DataStorageManager>
#property (nonatomic,strong) DataPlistManager *plistManager;
- (void) saveFile;
#end
and its implementation
#import "DataAdapter.h"
#implementation DataAdapter
-(id) initWithDataPlistManager:(DataPlistManager *) manager
{
self = [super init];
self.plistManager = manager;
self.plistManager.delegate = self;
return self;
}
- (void) saveFile
{
[self.plistManager savePlist];
}
#end
Your DataPlistManager needs a property delegate:
#property (weak) id<DataStorageManager> delegate;
If you add #import "DataAdapter.h" in your "DataPlistManager.h" file then remove it and add it to "DataPlistManager.m" file, I don't know but some days ago i have same issue, and i solved it by using this trick :)
DataManager class contains delegate property so you should set your object as delegate of DataManager class and call method (send message) saveFile inside delegate class:
#implementation DataAdapter
- (void)someMethod) {
DataManager *dataManagerObject = [[DataManager alloc] init];
dataManagerObject.delegate = self;
}
#implementation DataManager
- (void)someDelegateMethod {
[self.delegate saveFile];
}
Are you sure you understand concept of delegation pattern?
https://developer.apple.com/library/ios/documentation/general/conceptual/CocoaEncyclopedia/DelegatesandDataSources/DelegatesandDataSources.html
I want to allow deep copy of my class object and am trying to implement copyWithZone but the call to [super copyWithZone:zone] yields the error:
error: no visible #interface for 'NSObject' declares the selector 'copyWithZone:'
#interface MyCustomClass : NSObject
#end
#implementation MyCustomClass
- (id)copyWithZone:(NSZone *)zone
{
// The following produces an error
MyCustomClass *result = [super copyWithZone:zone];
// copying data
return result;
}
#end
How should I create a deep copy of this class?
You should add the NSCopying protocol to your class's interface.
#interface MyCustomClass : NSObject <NSCopying>
Then the method should be:
- (id)copyWithZone:(NSZone *)zone {
MyCustomClass *result = [[[self class] allocWithZone:zone] init];
// If your class has any properties then do
result.someProperty = self.someProperty;
return result;
}
NSObject doesn't conform to the NSCopying protocol. This is why you can't call super copyWithZone:.
Edit: Based on Roger's comment, I have updated the first line of code in the copyWithZone: method. But based on other comments, the zone can safely be ignored.