Objective C - Get a class to return a value - objective-c

I rarely ask questions, but this one is frustrating me as I can not find an answer anywhere!
I just need to call the function in GameChallenges.m and return the value to the view controller. GameChallenges.m will be called by different view controllers, thats why its separate. Please help!
I have a separate class file called GameChallenges.
This has a function/method in it:
in the .h
#class StatsViewController;
#interface GameChallenges : NSObject {
StatsViewController* statsController;
NSString* challengeTitle;
}
#property (nonatomic, retain) IBOutlet StatsViewController* statsController;
#property (assign) NSString* challengeTitle;
-(NSString*)checkChallenge:(int)challegeID;
#end
in the .m
#import "GameChallenges.h"
#import "StatsViewController.h"
#implementation GameChallenges
#synthesize challengeTitle,statsController;
-(NSString*)checkChallenge:(int)challegeID{
if(challegeID==1){
self.challengeTitle = #"Some Text.";
return challengeTitle;
}else if(challegeID==2){
self.challengeTitle = #"Some Other Text.";
return challengeTitle;
}
}
From a view controller called StatsViewController I am calling this method
in the .h
#class GameChallenges;
#interface StatsViewController : UIViewController {
UILabel* challengeIDDescText;
}
#property (nonatomic, retain) IBOutlet UILabel* challengeIDDescText;
#property (nonatomic, retain) IBOutlet GameChallenges* challenges;
#end
in the .m
[challenges checkChallenge:tempString];
challengeIDDescText.text = challenges.challengeTitle;

Your code is quite weird, I'd say this is what's happening:
-[GameChallenges checkChallenge] seems to expect an int and you call it with a variable called tempString that I guess is an NSString *. More likely than not, your method is ending without assigning challengeTitle and without a valid return value. Fix it with return nil as last statement and passing an int.
This kind of problems are very easy to solve using the debugger.
Also, have a look to Apple samples.

I'm beginner in objective-C, however, code in the GameChallenges.m looks weird to me... Wouldn't this be better?
challengeIDDescText.text = [challenges checkChallenge:challengeId];

Related

How to view data from NSTextField Correctly?

Hi i've recently completed a tutorial book on the basics of objective c. And now I'm "Attempting" to make a simple application. Right now I seem to be having the simplest issues which i cannot seem to fix, maybe you could tell me what i'm doing incorrectly.
AppDelegate.h
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (assign) IBOutlet NSWindow *window;
- (IBAction)saveData:(id)sender;
//Below is a simple IBOutlet which I try to retrieve data from when the IBAction saveData occurs
#property (weak) IBOutlet NSTextField *foodName;
#end
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
}
//Here is the saveData IBAction which should print out the value of the NSTextField if the user entered a value (if not returns null)
- (IBAction)saveData:(id)sender {
NSLog(#"%#", foodName.stringValue);
NSLog(#"Saved");
}
#end
The problem I seem to have is the build will fail and give me an error message on this line in AppDelegate.m:
NSLog(#"%#", foodName.stringValue);
the error message is: Use of undeclared identifier 'foodName'; did you mean '_foodName'?
Could someone please explain whats going on and how I can overcome this?
To address the getter method, use self.:
NSLog(#"%#", self.foodName.stringValue);
Also, a minor point: group all your #property declarations together at the start of the #interface statement, but after any instance variable declarations:
#interface MyClass : NSObject {
NSString *_str1;
int _i1;
}
#property (weak) IBOutlet NSString *something;
#property (strong, readonly) NSNumber *somethingElse;
- (int)aMethod:(NSString *)string;
- (void)anotherMethod;
#end

Obtaining the string value from separate window to be used on another. Objective C

I have a window with a large NSTextFeildCell, where text can be modified. Upon clicking a button another window appears where the text from the original window can be used some how. The issue I am having is when I attempt to retrieve that text the log spits out...
" -[NSTextView stringValue]: unrecognized selector sent to instance 0x100151860"
Fallowed by a long trace...
I have tried to solve this several different ways but with no luck.
currently,
First window controller
.h
#import <Cocoa/Cocoa.h>
#class NextWindowController;
#interface TextViewWindowController : NSWindowController
#property (nonatomic, weak) NextWindowController *NextWindow;
#property (nonatomic, weak) IBOutlet NSTextFieldCell *txtTextView;
- (IBAction)btnClicked:(id)sender;
- (NSString*)getText;
#end
.m
#import "TextViewWindowController.h"
#import "NextWindowController.h"
#implementation TextViewWindowController
#synthesize NextWindow;
- (IBAction)btnClicked:(id)sender{
[NextWindow setCallingWindow:self];
[NextWindow showWindow:self];
}
- (NSString*)getText{
return [_txtTextView stringValue];// there is a problem with the view...
}
#end
Next Window controller
.h
#import <Cocoa/Cocoa.h>
#class TextViewWindowController;
#interface NextWindowController : NSWindowController{
NSMutableString* str;
}
#property (nonatomic, weak) TextViewWindowController *callingWindow;
#end
.m
#import "NextWindowController.h"
#import "TextViewWindowController.h"
#implementation NextWindowController
#synthesize callingWindow;
- (IBAction)btnEnterClicked:(id)sender{
[str setString:callingWindow.txtTextView.stringValue];
}
- (id)initWithWindow:(NSWindow *)window{
self = [super initWithWindow:window];
if (self) {
str = [[NSMutableString alloc] init];
}
return self;
}
#end
I have also tried str = [callingWindow getText] with the same result.
Any help would be very appreciated!
It's not super intuitive to figure out from Apple's documentation, but to get the raw string value of a NSTextView (which inherits from NSText), just use:
[_txtTextView string];
And since you're using properties, it might be smarter to use the accessor in your function, like this:
- (NSString*)getText{
return [self.txtTextView string];
}

iOS object is identifying as wrong class

So long story short, I have some odd bugs in some code I'm messing with and it turns out that it comes from an object being identified as the wrong class.
Here is my code, with the NSLog statement I put before anything touches the object... I can't figure out why it's showing as the wrong class.
Photo.h
#interface Photo : NSObject
{
}
#property (nonatomic, retain) UIImage *image;
#property (nonatomic, retain) IBOutlet NSString *descr;
#end
Photo.m
#implementation Photo
#synthesize image;
#synthesize descr;
#end
CameraViewController.h
#include "Photo.h"
#interface CameraViewController : UIViewController <UIImagePickerControllerDelegate>
{
IBOutlet UIImageView *imageView;
}
#property (nonatomic, retain) Photo *photo;
-(void)takePhoto;
-(void)resetImage;
#end
and finally...
CameraViewController.m
#import "Photo.h"
....
#implementation CameraViewController
#synthesize photo;
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%#", NSStringFromClass([_photo class]));
// Do any additional setup after loading the view.
}
This prints out:
UIImageView
I would expect it to print out
Photo
or at the very least
NSObject
Am I missing something???
Sending an object the class message retrieves that object's dynamic type. The object must be assigned prior to querying it for its class. In other words, declaring a property as Photo* is not sufficient for its class to return Photo: you must also assign it an instance of Photo or one of its subclasses. In the later case, the result of sending class message will be different (i.e. the Class of the subclass will be returned).

is this "property not found" error an XCode bug or a coding mistake on the part of a newbie? [duplicate]

Right before my model class sends the variable stringToDisplay, NSLog shows me that it has a value. But when I try to use it in my ViewController, I just get (null). Any thoughts about what I'm doing wrong?
(The good news is that, while working on this, I had sort of a breakthrough in understanding how models and controllers relate to each other. I'm still a complete newbie, but I don't feel quite as lost as I did.)
Here's what I think is the relevant code:
CalculatorBrain.h
#import <Foundation/Foundation.h>
#interface CalculatorBrain : NSObject
#property (nonatomic) NSMutableString *stringToAdd;
#property (nonatomic,strong) NSString *stringForDisplay;
- (double)performOperation:(NSString *)operation withArray:(NSMutableArray *)particularStackYouNeedToPopOff;
CalculatorBrain.m
#implementation CalculatorBrain
#synthesize stringToAdd = _stringToAdd;
#synthesize stringForDisplay = _stringForDisplay;
#synthesize whatHappenedSinceLastClear = _whatHappenedSinceLastClear;
- (double)performOperation:(NSString *)operation withArray:(NSMutableArray *)particularStackYouNeedToPopOff
{
<long code that I think doesn't matter because this NSLog produces exactly what I want it to:>
NSLog(#"%#",stringForDisplay);
return result;
}
CalculatorViewController.h
#import <UIKit/UIKit.h>
#interface CalculatorViewController : UIViewController
#property (nonatomic) NSArray *arrayOfDictionaries;
#property (nonatomic) NSDictionary *dictionary;
#property (weak, nonatomic) IBOutlet UILabel *variablesUsed;
#property (nonatomic, strong) NSString *operation;
#end
CalculatorViewController.m
#import "CalculatorViewController.h"
#import "CalculatorBrain.h"
#interface CalculatorViewController ()
#property (nonatomic,strong) CalculatorBrain *brain;
#end
#implementation CalculatorViewController
#synthesize display = _display;
#synthesize history = _history;
#synthesize brain = _brain;
#synthesize operation = _operation;
- (IBAction)operationPressed:(UIButton *)sender
{
NSString *otherString=[self.brain stringForDisplay];
if (self.userIsEnteringNumber) [self enterPressed];
NSString *operation = sender.currentTitle;
double result = [self.brain performOperation:operation withArray:[self.brain whatHappenedSinceLastClear]];
self.display.text = [NSString stringWithFormat:#"%g",result];
self.history.text = otherString;
NSLog(#"%#",otherString);
}
And the NSLog in that last line of code give me (null).
Any thoughts?
Maybe I'm missing something but your property is declared in the class extension of CalculatorBrain so nobody outside CalculatorBrain.m knows about this property.
So if you want to expose this property to other objects, you will have to declare it in CalculatorBrain.h instead.
Oh - your declaration of the property whatHappenedSinceLastClear isn't exposed to other classes that import CalculatorBrain.h because you put the property declaration in an interface extension in the .m file, which other classes will not see.
To make it publicly accessible move the #property line for whatHappenedSinceLastClear to CalculatorBrain.h, not the .m file.
I can guess that problem lies in the way you assign your stringForDisplay, eg.:
if you use something like
stringForDisplay_ = anotherString;
setter for property doesn't fire, so you have to retain your variable yourself otherwise it'll live just until your method finishes;
If so - use property setters, eg.:
self.stringForDisplay = anotherString;
that way ARC will do all the memory management.
It really depends how you set stringForDisplay inside the performOperation:withArray: method.
for a blind guess, try using
NSString *otherString = self.brain.stringForDisplay;
after this line
double result = [self.brain performOperation:operation withArray:[self.brain whatHappenedSinceLastClear]];

Setting variables in a different class in Cocoa

I'm trying to learn how to set variables for different classes using one main data class.
Here's a diagram of of what I would like to do and the code from my project:
ClassA
#import <Foundation/Foundation.h>
#interface ClassA : NSObject {
NSString *stringA;
NSString *stringB;
}
#property (nonatomic, copy) NSString *stringA;
#property (nonatomic, copy) NSString *stringB;
#property (weak) IBOutlet NSTextField *textA;
#property (weak) IBOutlet NSTextField *textB;
- (IBAction)displayStrings:(id)sender;
#end
#import "ClassA.h"
#implementation ClassA
#synthesize stringA, stringB, textA, textB;
- (IBAction)displayStrings:(id)sender {
[textA setStringValue:stringA];
[textB setStringValue:stringB];
}
#end
Class X
#import <Foundation/Foundation.h>
#interface ClassX : NSObject {
NSMutableString *stringX;
}
- (void)theVariables:(id)sender;
#end
#import "ClassX.h"
#import "ClassA.h"
#implementation ClassX
- (void)awakeFromNib {
[self theVariables:self];
}
- (void)theVariables:(id)sender {
stringX = [[NSMutableString alloc] init];
ClassA *clssA = [[ClassA alloc] init];
[stringX setString:#"stringX for stringA"];
[clssA setStringA:stringX];
[stringX setString:#"stringX for stringB"];
[clssA setStringB:stringX];
}
#end
No errors show up in the code, but when I run the program I am receiving an error about "Invalid parameter not satisfying: aString". It looks like the setStringValue for the IBOutlet is not working. Any suggestions?
I'm not seeing the error you mention, but as far as I can tell from your code, the main problem is this line:
ClassA *clssA = [[ClassA alloc] init];
You must have an instance of ClassA in your xib, which is connected to text fields and a button. That object in the xib is a real object, and if you just create another instance of ClassA somewhere in your code, you have an entirely different object that has no connection to the one that's in your xib.
You need to make sure of/change two things. First, there needs to be an instance of ClassX in your xib. Second, ClassX needs an outlet to a ClassA instance:
#class ClassA; // Declare ClassA so you can use it below
#interface ClassX : NSObject
#property (weak) IBOutlet ClassA * theClassAInstance;
- (void)theVariables:(id)sender;
#end
Which should then be connected in the xib file. Then, in theVariables:, you just use that outlet instead of creating a new instance of ClassA: [[self theClassAInstance] setStringA:#"stringX for stringA"];
Three points of style:
First, you should be importing Cocoa.h: #import <Cocoa/Cocoa.h> instead of Foundation.h in any class that touches the GUI (ClassA in this case). That's where stuff like NSTextField is defined. It works anyways because Cocoa.h is imported via your .pch file, but it's best to be explicit.
Second, creating a mutable string and changing its value to two different literal strings doesn't make a whole lot of sense. Just use the literals directly: [clssA setStringA:#"stringX for stringA"];
Third, You don't need to declare the instance variables separately; #synthesize creates them for you, and it is now the recommended practice to not declare them:
#interface ClassA : NSObject
#property (nonatomic, copy) NSString *stringA;
#property (nonatomic, copy) NSString *stringB;
#property (weak) IBOutlet NSTextField *textA;
#property (weak) IBOutlet NSTextField *textB;
- (IBAction)displayStrings:(id)sender;
#end
Last (four points!), you should really be accessing the values of stringA and stringB in ClassA via the property: [textA setStringValue:[self stringA]];