'Property not found' in subclass constructor - objective-c

I have the next code:
GenericClass.h:
#interface GenericClass : NSObject
#property (nonatomic) char tile_inicial;
#property (strong, nonatomic) NSString *color;
GenericClass.m
#implementation GenericClass
-(id)init
{
self = [super init];
return self;
}
- (id)initTodo:(char) tile
{
_tile_inicial = tile;
return self;
}
#end
Animals.h:
#import "GenericClass.h"
#interface Animals : GenericClass
#property (nonatomic) bool fly;
#property (strong, nonatomic) NSString *sound;
#end
#interface Cow : Animals
#property (nonatomic) bool daLeche;
#end
Animals.m
#import "Animals.h"
#implementation Animals
-(id)init
{
self = [super init];
return self;
}
- (id)initAnimal:(bool)fly :(NSString *) sound :(char) tile
{
_fly = fly;
_sound = sound;
self = [super initTodo: tile];
return self;
}
#end
#implementation Cow
-(id)init
{
self = [super initAnimal: false :#"Muu Muu": 'v'];
if (self) {
_daLeche = true;
}
return self;
}
#end
The issue is I would like to call directly from the Cow constructor to any property (for example color or sound) and initialize it.
But if I try to do it without call the parent constructor it returns: "Property not found"
Any idea?
Thanks in advance

Related

Will there be retain cycle?

Here is some abstract code. There is base class "BaseClass" and child class "MyClass"
BaseClass
#property (nonatomic, copy) BlockType block;
- initBaseClassWithBlock:(BlockType)block {
self = [super init];
if (self) {
self.block = block;
}
return self;
}
MYClass : BaseClass
#property (strong, nonatomic) NSString *myString;
- (instancetype)init {
self = [super initBaseClassWithBlock:^{
NSLog(#"%#", self.myString);
}
return self;
}
Will there be retain cycle in MyClass init method?
Yes; that is a retain cycle.
You can check by pasting the code into a simple project and then using Xcode 8's memory graph debugger.
Copy/paste this compilable version of your code then build and run. It'll run forever and do nothing. Click the little object graph debugger icon (the three circles with lines in them) and it'll show you that you have a strong reference from the instance of sub back to itself via the block.
#interface Base:NSObject
#property (nonatomic, copy) dispatch_block_t block;
#end
#interface Sub:Base
#property (strong, nonatomic) NSString *myString;
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
Sub *s = [[Sub alloc] init];
}
dispatch_main();
return 0;
}
#implementation Base
- initBaseClassWithBlock:(dispatch_block_t)block
{
self = [super init];
if (self) {
self.block = block;
}
return self;
}
#end
#implementation Sub
- (instancetype)init {
if (self = [super initBaseClassWithBlock:^{
NSLog(#"%#", self.myString);
}]) {
;
}
return self;
}
#end

Using custom method to add objects to NSMutableArray Objective C

I am new to Objective C, I'm trying to add objects to NSMutableArray that I can use multiple times on my project. I have a Model class as
History.h
import
#interface History : NSObject
#property (nonatomic) NSString *itemName;
#property (nonatomic) int quantity;
#property (nonatomic) double total;
#property (nonatomic) NSDate *purchaseDate;
- (instancetype)initWithName: (NSString*)itemName withQuantity:(int)quantity withTotal:(double) total withPurchaseDate:(NSDate*) purchaseDate;
#end
History.m
#import "History.h"
#implementation History
-(instancetype)initWithName: (NSString*)iName withQuantity:(int)iQuantity withTotal:(double) iTotal withPurchaseDate:(NSDate*) iPdate {
self = [super init];
if(self) {
self.itemName = iName;
self.quantity = iQuantity;
self.quantity = iQuantity;
self.purchaseDate = iPdate;
}
return self;
}
#end
Repository.h
#import <Foundation/Foundation.h>
#interface Repository : NSObject
#property (nonatomic) NSMutableArray *itemHistory;
-(void) pushToArray:(NSString *)name withQuantity:(int)qty withTotal:(double) total withPurchaseDate:(NSDate*) pDate;
#end
Repository.m
#import "Repository.h"
#import "History.h"
#interface Repository()
//#property (nonatomic) NSMutableArray *itemHistory;
#end
#implementation Repository
-(NSMutableArray *) itemHistory {
if(_itemHistory == nil) {
_itemHistory = [[NSMutableArray alloc] init];
}
return _itemHistory;
}
This is my method that I want to use to add objects to the MutableArray.
-(void) pushToArray:(NSString *)name withQuantity:(int)qty withTotal:(double) total withPurchaseDate:(NSDate*) pDate {
self.itemHistory = [[NSMutableArray alloc] init];
History *obj = [[History alloc] init];
obj.itemName = name;
obj.quantity = qty;
obj.total = total;
obj.purchaseDate = pDate;
[self.itemHistory addObject:obj];
}
#end
Thank you for your help in advance.
Every time you call pushToArray:... you are replacing the existing itemHistory with a new, empty, mutable array. You'll only ever see the last item to be pushed in that array.
However, you also don't need to lazily initialize _itemHistory. Just create an instance in your init method and be done with it. Saves confusion and refactoring hell.
In your Repository class, simply implement the designated initializer:
- (instancetype) init
{
if (self=[super init]) {
_itemHistory = [[NSMutableArray alloc] init];
}
return self;
}
Uncomment the property:
#interface Repository()
#property (nonatomic) NSMutableArray *itemHistory;
#end
And remove this from the -pushToArry:... method:
//self.itemHistory = [[NSMutableArray alloc] init];
If it still doesn't work, you need to show how you are logging the failure.

"No visible #interface" error with method

CJSHWork as a class is defined in CJSHWork.h and CJSHWork.m. In CJSHWork.h I have:
#interface CJSHWork : NSObject
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *url;
-(id) initWithName:(NSString *)name filename:(NSString *)title content:(NSString *)url;
#end
In CJSHWork.m I have:
- (id) initWithName:(NSString *)name title:(NSString *)title content:(NSString *)url
{
self = [super init];
if (self)
{
_name = name;
_title = title;
_url = url;
}
}
And I have, in CJSHDataController.m,
import "CJSHWork.h"
...
CJSHWork *work = [[CJSHWork alloc] initWithName:#"" title:allWorks[i][1] url:url];
This gets the error "No visible #interface for CJSHWork declares the selector initWithName title url".
What is going on here, and how can I fix it?
Your method name is initWithName:title:content: not initWithName:title:url:

How to implement initWith method passing custom object as an argument?

For instance I have following class:
#interface PrivateInfo: NSObject
- (instancetype)initWithPrivateInfoObject:(PrivateInfo *)pi;
#end
#implementation PrivateInfo
{
#private
NSString *name;
NSString *creditCardID;
}
- (instancetype)initWithPrivateInfoObject:(PrivateInfo *)pi
{
// how to init current object with passed pi ?
}
- (PrivateInfo *)copy
{
// how to create a copy of current object?
}
#end
Assuming ARC:
.h:
#interface PrivateInfo: NSObject <NSCopying>
- (instancetype)initWithPrivateInfoObject:(PrivateInfo *)pi;
#end
.m:
#implementation PrivateInfo {
NSString *name;
NSString *creditCardID;
}
- (instancetype)initWithPrivateInfoObject:(PrivateInfo *)pi
{
self = [super init];
if (self) {
name = pi->name;
creditCardID = pi->creditCardID;
}
return self;
}
- (PrivateInfo *)copyWithZone:(NSZone *)zone {
PrivateInfo *res = [[PrivateInfo alloc] initWithPrivateInfoObject:self];
return res;
}
#end
You don't need #private in the #implementation block for declaring ivars. And use the NSCopying protocol is you want to copy objects.

My delegate action is not called in Cocoa

I have a class which has it's delegate:
#protocol SNIRCControllerDelegate
- (void) serverTalked:(id)data;
#end
#interface SNIRCController : NSObject <NSStreamDelegate> {
id<SNIRCControllerDelegate> delegate;
}
- (void) setDelegate:(id<SNIRCControllerDelegate>)_delegate;
- (void) test;
#end
The implementation:
#implementation SNIRCController
- (void) setDelegate:(id<SNIRCControllerDelegate>)_delegate {
_delegate = delegate;
}
- (void) test {
[delegate serverTalked:#"test"];
}
But for some reason [delegate serverTalked:#"test"]; doesn't calls the delegate :/
This is how I do it on the AppDelegate:
#interface AppDelegate : NSObject <NSApplicationDelegate, NSStreamDelegate, SNIRCControllerDelegate> {
IBOutlet NSTextView *logField;
SNIRCController *ircController;
}
#property (assign) IBOutlet NSWindow *window;
-(void)writeToLog:(NSString*)data;
#end
#implementation AppDelegate
#synthesize window = _window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
ircController = [[SNIRCController alloc] init];
[ircController setDelegate:self];
[ircController test];
}
- (void) serverTalked:(id)data {
NSLog(#"got called :D");
}
-(void)writeToLog:(NSString*)data {
NSAttributedString *stringToAppend = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:#"%#\n", data]];
[[logField textStorage] appendAttributedString:stringToAppend];
}
But serverTalked: doesn't gets called :( what I'm doing wrong?
In your implementation of setDelegate:, this:
_delegate = delegate;
should be:
delegate = _delegate;
You got confused and swapped ivar and parameter. The confusion might have been caused by the fact that the underscore prefix is more commonly used for ivars. In your case, it is the parameter that is prefixed with an underscore.