Hi
i dont know why i call a function in "msg" class
it has no respond:(
this is the "msg" class:
msg.h :
#import <UIKit/UIKit.h>
#interface msg : NSObject {
}
-(void) Print;
#end
msg.m :
#import "msg.h"
#implementation msg
-(void) Print {
NSLog(#"Hello World");
}
#end
viewController.h :
#import <UIKit/UIKit.h>
#import "msg.h"
#class msg;
#interface ClassMod4ViewController : UIViewController {
msg *object;
}
#property (nonatomic,retain) msg *object;
#end
viewController.m :
#import "ClassMod4ViewController.h"
#implementation ClassMod4ViewController
#synthesize object;
- (void)viewDidLoad {
[object Print];
[super viewDidLoad];
}
Thanks
Was the object initialized in the designated initializer (usually initWithNibName:bundle: for UIViewController subclasses) prior to viewDidLoad being invoked?
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
// ...
object = [[Msg alloc] init];
// ...
return self;
}
If the object has not been initialized, then it's nil. Remember that it's okay to send nil objects messages in Objective-C (nothing will happen as a result).
have you tried:
- (void)viewDidLoad {
assert(object);
[object Print];
[super viewDidLoad];
}
?
if the assertion fails, then the pointer to object is 0 (or nil). you must create the object before you use it. this is typically performed in the initializer (in your case, of the class that contains the instance of object):
- (id)init {
self = [super init];
if (0 != self) {
object = [[msg alloc] init];
}
return self;
}
but sometimes you'll want to create the object later on.
if you are initializing it, then you may want to set breakpoints where the object is accessed in order to determine where the object is set to 0.
Related
I created an object called Model that has some methods. I want to import Model into Mediator to use its methods there. But when I try to do this in Mediator.m I keep getting errors:
Initializer element is not a compile-time constant & No known class method for selector 'add'
I'm confused at to what these error are getting at. Researching them has not made things more clear.
Model.h
#interface Model : NSObject
#property (nonatomic) NSInteger tally;
-(int) add;
#end
Model.m
#import "Model.h"
#interface Model ()
#end
#implementation Model
- (instancetype)init
{
self = [super init];
if (self) {
self.tally = 0;
}
return self;
}
- (int)add {
self.tally = self.tally + 1;
return self.tally;
}
#end
Mediator.h
#interface MediatorController : NSObject
- (int)addOne;
#end
Mediator.m
#interface MediatorController ()
#end
#implementation MediatorController
Model *model = [[Model alloc] init]; <<<<<<< "Initializer element is not a compile-time constant"
- (int)addOne {
return [Model add]; <<<<<< "No known class method for selector 'add"
}
#end
First, you'll need a model property on your MediatorController
#interface MediatorController : NSObject
#property (strong, nonatomic) Model* model; //<-- Here
- (int)addOne;
- (int)subtractOne;
- (void)setValue:(int)value;
- (int)value;
#end
Then, you need an init method -- right now, you're trying to write your model = at the top level of the implementation, which doesn't work -- it needs to be inside a method.
Lastly, instead of calling add on Model (which is the class), call it on self.model, which is the instance of the class.
#implementation MediatorController
- (instancetype)init { //< -- Here
if (self = [super init]) {
self.model = [Model new];
}
return self;
}
- (int)addOne {
return [self.model add];
}
#end
You'll end up with a few compiler warnings because you haven't implemented the rest of the methods yet (subtractOne, setValue, etc), but this will get you started.
I am updating some legacy objective C code to be able to be compiled under OSX 10.13. The legacy code worked and most of the update code does as well except for an NSSoundDelegate that needs to handle a didFinishPlaying function. The delegate method is not being called. The delegate method is contained in a class called MyClass. Here is relevant code.
In MyClass.h:
#class MyClass;
#protocol MyClass <NSObject>
#optional
- (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)flag;
#end
#interface MyClass : NSObject <NSSoundDelegate>
{
}
#property (nonatomic, assign) id <NSSoundDelegate> delegate;
- (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)flag;
- (id) init;
#end
Then in MyClass.m:
#implementation MyClass
#synthesize delegate;
- (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)flag
{
if (flag) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"handleNSSoundDidFinishPlaying" object:sound];
}
}
- (id)init
{
MyClass *thePointer;
self = [super init];
if (self) {
thePointer = self;
self.delegate = (id)thePointer;
isInitialized = NO;
isClosing = NO;
[self set_currentSounds:[NSMutableArray arrayWithCapacity:0]];
}
return self;
}
#end
Can anyone see what I'm missing?
I think you should notify the delegate object like:
if([_delegate respondsToSelector:#selector(sound: didFinishPlaying:)])
[_delegate sound:self didFinishPlaying:_flag];
Hope this will help you.
Found the problem! When allocating the sound to be played, you have to set the sounds delegate using [theSnd setDelegate:self]; so that when the sound stops playing, the delegate gets called, in this case the delegate is in the MyClass .m file.
I have a strange problem in my Cocoa-app. I have a main window with an NSTableView in it with a controller class (PropValTableHandler). I have made the connections between my NSTableView and the PropValTableHandler, but when the 'numberOfRowsInTableView' method is called it looks like not the 'PropValTableHandler' initialized in 'AddDelegate' is used, since the 'propMan' field is not initialized (it is like the normal init is used, so it has to be another instance of this class).
Am I doing something wrong? I have another NSTableView handler in another window, that works, but it does not have a custom init method.
Source codes:
AppDelegate
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize propValTableController = _propValTableController;
-(id) init
{
self = [super init];
if (self)
{
_propMan = [[OCPropertyManager alloc]initWithPath:"./data/"];
_propValTableController = [[PropValTableHandler alloc]
[initWithPropManager:_propMan];
}
return self;
}
PropValTableHandler
#interface PropValTableHandler : NSObject <NSTableViewDataSource>
#property IBOutlet NSTableView * constants;
#property OCPropertyManager * propMan;
-(id) initWithPropManager:(OCPropertyManager*)pm;
-(NSInteger) numberOfRowsInTableView:(NSTableView *)tableView;
#end
#import "PropValTableHandler.h"
#implementation PropValTableHandler
-(id) initWithPropManager:(OCPropertyManager*)pm
{
self = [super self];
if (self)
{
self.propMan = pm;
}
return self;
}
/*********** TABLEVIEW DATASOURCE ******************/
-(NSInteger) numberOfRowsInTableView:(NSTableView *)tableView
{
NSInteger count = [_propMan.consts count];
return count;
}
/**************************************************/
#end
I have solved the problem by adding a
#property IBOutlet AppDelegate *parent;
for the PropValTableHandler class and making the connections.
This way I can use:
parent.propMan
where ever I need it without passing a reference to it in the init method.
I was trying this sample program below.
I'm not calling the +(void)initialise and -(id)init method in the class B.But its getting called automatically.
Is the -(void)initialise is equal to the default constructor in objective C.
Does the [super init] points to the NSObject.
If i'm not using the -(id)init method i'm getting a warning that the class is with incomplete implementation.
ClassA.h
#import <Foundation/Foundation.h>
static int ab;
#interface ClassA : NSObject {
int a;
}
+ (void) initialize;
- (id) init;
- (void) displayNumOfInstance;
- (void) disp;
#end
ClassA.m
#import "ClassA.h"
#implementation ClassA
+ (void) initialize
{
ab=0;
}
- (id) init
{
self = [super init];
if (self!=nil) {
ab++;
}
return self;
}
- (void) displayNumOfInstance
{
NSLog(#"Number of instances of this class:%d",ab);
}
- (void) disp
{
NSLog(#"The value is %d",ab);
}
#end
ClassB.h
#import <Foundation/Foundation.h>
#import "ClassA.h"
#interface ClassB : ClassA {
}
- (void) display;
#end
ClassB.m
#import "ClassB.h"
#implementation ClassB
- (void) display
{
ab=20;
NSLog(#"The value ab is %d",ab);
}
#end
class2.m
#import <Foundation/Foundation.h>
#import "ClassA.h"
int main (int argc, const char * argv[]) {
ClassA *a = [[ClassA alloc]init];
[a disp];
[a release];
ClassB *b = [[ClassB alloc]init];
[b display];
[b release];
ClassA *a1 = [[ClassA alloc]init];
[a1 disp];
[a1 release];
ClassB *b1 = [[ClassB alloc]init];
[b1 display];
[b1 release];
return 0;
}
Output:
2011-04-30 15:31:42.490 class2[1674:a0f] 1
2011-04-30 15:31:42.493 class2[1674:a0f] The value ab is 20
2011-04-30 15:31:42.494 class2[1674:a0f] 2
2011-04-30 15:31:42.495 class2[1674:a0f] The value ab is 20
The default construction usually start with has the following format -init or any variant upon this, e.g. -initWithFrame:.
The method +initialize is a class method (static method) that's called at least once when your application starts. You can use this method to initialize static variables that are useful across all instances of the class. This method might be useful to e.g. initialize a shared cache or a shared lookup map for a class.
For NSObject the -init method is the designated initializer, but for other classes this might differ. Apple documents the designated initializer in it's class headers using the NS_DESIGNATED_INITIALIZER macro. For example UIView subclasses should override -initWithFrame: and -initWithCoder: instead, as these methods are marked as designated initializer.
When subclassing and implementing a custom designated initializer, don't forget to initialize the super class as well. Let's for example have a UIView subclass that has a custom designated initializer -initWithFrame:title:. We would implement it as follows:
// A custom designated initializer for an UIView subclass.
- (id)initWithFrame:(CGRect)frame title:(NSString *)title
{
// Initialize the superclass first.
//
// Make sure initialization was successful by making sure
// an instance was returned. If initialization fails, e.g.
// because we run out of memory, the returned value would
// be nil.
self = [super initWithFrame:frame];
if (self)
{
// Superclass successfully initialized.
self.titleLabel.text = title
}
return self;
}
// Override the designated initializer from the superclass to
// make sure the new designated initializer from this class is
// used instead.
- (id)initWithFrame:(CGRect)frame
{
return [[self alloc] initWithFrame:frame title:#"Untitled"];
}
More details on initialising can be found on the Apple Developer website:
Object Initialization
Multiple Initializers
I have a class called "CardSet", containing an NSMutableArray* cardSet to hold "cards", which I extend to make "DeckCards". I'd like "CardSet" to have a method called "(void)addCard:(Card*)" (and similarly a method "removeCard"). I'd like "addCard" to some how have access to and set cardSet. Even better I'd like to use the "addCard" method to initialise cardSet. The class file "CardSet.h" reads:
#import < Cocoa/Cocoa.h >
#import < Card.h >
#interface CardSet : NSObject {
NSMutableArray* cardSet;
}
-(id)init;
-(NSMutableArray*)getCardSet;
-(void)setCardSet:(NSMutableArray *)new_cardset;
-(Card*)getCard:(NSInteger) index;
**-(void)addCard:(Card*) new_card;**
-(void)removeCard:(Card*) old_card;
-(void)dealloc;
#property (readwrite, retain, getter=getCardSet, setter=setCardSet) NSMutableArray* cardSet;
#end
and the method file reads:
#import "CardSet.h"
#implementation CardSet
-(id)init{
if( self = [super init] ){} //will add initialisations here later
return self;
}
-(NSMutableArray*)getCardSet{
return cardSet;
}
-(void)setCardSet:(NSMutableArray *)new_cardSet{
cardSet = new_cardSet;
}
-(Card*)getCard:(NSInteger)index{
return [cardSet objectAtIndex:index];
}
**-(void)addCard:(Card *)new_card{
[cardSet addObject:new_card];
}**
-(void)removeCard:(Card *)old_card{
[cardSet removeObject:old_card];
}
-(void)dealloc{
[cardSet release];
[super dealloc];
}
#synthesize cardSet;
#end
This compiles just fine. I'd like to initialise a "DeckCards" instance using its "addCard" method 52 times. When I call addCard 52 times in a DeckCards setter method, and ask for the size of its "cardSet", I'm returned 0.
This appears to be a scope or privileges problem? Can the "addCard" method have any setter privileges? Must a setter argument be the same as the return and respective member type?
[I can work around the above by creating an NSMutableArray object "deck_cards_temp" outside of "DeckCard", add 52 cards to this, and pass it to set the member of my "DeckCards" instance via the setter inherited from "CardSet". This is not very satisfactory!]
What do you advise? Many thanks in advance for your help and patience.
You are never actually creating the cardSet object. You should be creating it in your -init method:
-(id)init
{
if( self = [super init] )
{
cardSet = [[NSMutableArray alloc] init];
}
return self;
}
Because you never actually create the array, all the calls to -addCard: are being sent to a nil object.
When you pass in an array to -setCardSet:, you are passing in an initialized array so the array is no longer nil and the -addCard: calls work fine.
CardSet.h
#import <Cocoa/Cocoa.h>
// For know we just need to know there is a class named "Card" being used but implemented later
#class Card;
#interface CardSet : NSObject {
NSMutableArray *cardSet;
}
// Here are the methods according to "correct" naming conventions
- (Card *)cardAtIndex:(NSInteger)index;
- (void)addCard:(Card *)card;
- (void)removeCard:(Card *)card;
// This will help us and forget about writing the setter/getter
#property (nonatomic, retain) NSMutableArray *cardSet;
#end
CardSet.m
#import "CardSet.h"
// Now we tell the compiler what "Card" is and what methods etc. it has
#import "Card.h"
#implementation CardSet
#synthesize cardSet;
- (id)init {
if (self = [super init]) {
// If we don't create the cardSet, how are we able to work with it!?
NSMutableArray *anArray = [[NSMutableArray alloc] init];
self.cardSet = anArray;
[anArray release];
}
return self;
}
- (Card *)cardAtIndex:(NSInteger)index {
return [cardSet objectAtIndex:index];
}
- (void)addCard:(Card *)card {
[cardSet addObject:card];
}
- (void)removeCard:(Card *)card {
[cardSet removeObject:card];
}
- (void)dealloc {
[cardSet release];
[super dealloc];
}
#end
As Abizern already noted: Naming the array the same as your class is a bad thing.
I would shorten that init method:
- (id)init {
if (self = [super init]) {
// If we don't create the cardSet, how are we able to work with it!?
self.cardSet = [NSMutableArray array];
}
return self;
}