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]];
Related
So I'm trying to access the property isPortClosed(BOOL) in SerialPortController and its giving me an error, I'm kinda new to objective-c. I feel like this should work as I've got a reference to the class with *port. Here is a link to the project.
Error messages: ~/GroundStation/GroundStation/ViewController.m:16:22: Property 'isPortClosed' not found on object of type 'SerialPortController *'
#import <Cocoa/Cocoa.h>
#import "SceneView.h"
#import "SerialPortController.h"
#interface ViewController : NSViewController
#property (strong) IBOutlet SerialPortController *port;
#property (weak) IBOutlet SceneView *accelSceneView;
#end
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
while(!self.port.isPortClosed) {
}
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
// Update the view, if already loaded.
}
#end
SerialPortController.h class
#import <Foundation/Foundation.h>
#import <ORSSerial/ORSSerial.h>
#interface SerialPortController : NSObject <ORSSerialPortDelegate>
#property (nonatomic, strong) ORSSerialPort *serial;
#property (nonatomic, strong) ORSSerialPortManager *serialPortManager;
#property (nonatomic) NSInteger xAngle;
#property (nonatomic) NSInteger yAngle;
#property (nonatomic) NSInteger zAngle;
#property (nonatomic) NSString *stringBuffer;
#property (nonatomic) BOOL isPortClosed;
#end
From the downloaded project I see that you have two SerialPortController class definitions (one at the root directory, and one in /GroundStation/), and the latter doesn't have any public properties. You should have only one SerialPortController class definition linked in your project (the one with the public properties).
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
I have control something like this
#import <Foundation/Foundation.h>
#import "AQLevelMeter.h"
#import "AQPlayer.h"
#import "AQRecorder.h"
#interface SpeakHereController : NSObject {
IBOutlet UIBarButtonItem* btn_record;
IBOutlet UIBarButtonItem* btn_play;
IBOutlet UILabel* fileDescription;
IBOutlet AQLevelMeter* lvlMeter_in;
AQPlayer* player;
AQRecorder* recorder;
BOOL playbackWasInterrupted;
BOOL playbackWasPaused;
}
#property (nonatomic, retain) UIBarButtonItem *btn_record;
#property (nonatomic, retain) UIBarButtonItem *btn_play;
#property (nonatomic, retain) UILabel *fileDescription;
#property (nonatomic, retain) AQLevelMeter *lvlMeter_in;
#property (readonly) AQPlayer *player;
#property (readonly) AQRecorder *recorder;
#property BOOL playbackWasInterrupted;
#property BOOL isReport;
#property CFStringRef recordFilePath;
- (IBAction)record: (id) sender;
- (IBAction)play: (id) sender;
-(void) InitializeThePlayer;
#end
as we can see I added many properties like
#property BOOL isReport;
#property CFStringRef recordFilePath;
then I created uiview contains this control
#import <UIKit/UIKit.h>
#class SpeakHereController;
#interface SpeakHereViewController : UIViewController {
IBOutlet SpeakHereController *controller;
}
Now I want to access the properties of the control object so I say
- (void)viewWillAppear:(BOOL)animated {
[self ReportDirectory];
[controller setIsReport:self.iSReport ];
//controller.isReport = self.iSReport ;
[controller setRecordFilePath:(CFStringRef) self.DICOMpath];
//controller.recordFilePath = ;
}
the problem is that at the lines
[controller setIsReport:self.iSReport ];
[controller setRecordFilePath:(CFStringRef) self.DICOMpath];
there is warning say that
warning: no '-setIsReport:' method found
I made
#synthesize isReport;
#synthesize recordFilePath;
also if I replaced #class SpeakHereController; by #import "SpeakHereController.h" it raise a lot of errors , U can download the sample code from apple
and if I said controller.isReport = self.iSReport ; it raise error request for member 'isReport' in something not a structure or union
My question is how to call the properties in this control , am I missing something
Best regards
I tried
At the top of SpeakHereViewController.m you will need
import "SpeakHereController.h"
Otherwise when SpeakHereViewController.m is compiled, it is completely unaware of what methods and properties your SpeakHereController class has
It should run fine even with the warning because the property does exist. However, I agree with you that the warning needs to be dealt with.
You should synthesize those properties in .m file.
The syntax is like:
#synthesize isReport, recordFilePath;
How do I access IBOutlets that have been created in another class? For example, if I have an IBOutlet in Class A how can I access in Class B? If I can not access IBOutlets from other classes what is a work-around?
You'll need to make your IBOutlet a #property and define a getter for that property via #synthesize or you can define your own getter, here's an example of the former:
#interface ClassA : NSObject {
UIView *someView;
}
#property (nonatomic, retain) IBOutlet UIView *someView;
#end
#implementation ClassA
#synthesize someView;
...
#end
Then, in ClassB, you can do this:
#implementation ClassB
- (void) doSomethingWithSomeView {
ClassA *a = [ClassA new];
UIView *someView = [a someView];
//do something with someView...
}
...
#end
I have two classes, Class A and Class B, both of them are subclasses of UIViewController.
I class A I have an NSString and I want to use this NSString in class B.
ClassA.h:
#class ClassB;
#interface ClassA : UIViewController {
ClassB *classB;
NSString stringA;
}
#property (nonatomic, retain) ClassB *classB;
#property (nonatomic, retain) NSString *stringA;
#end
ClassA.m:
stringA = [NSString stringWithString:webView.request.URL.absoluteString];
ClassB.h:
#class ClassA;
#interface ClassA : UIViewController {
ClassB *classA;
NSString stringB;
}
#property (nonatomic, retain) ClassB *classA;
#property (nonatomic, retain) NSString *stringB;
#end
ClassB.m:
- (void)viewWillAppear:(BOOL)animated {
self.stringB = classA.stringA;
}
Of course I did #import for both classes.
For some reason I always get NULL I classB for stringB.
Thanks!
The following aren't clear:
is mainViewController actually an instance of ClassA?
is classA even an instance of ClassA, as you've declared it an instance of ClassB?
what is your real code, as the things you've pasted here don't compile?
when in the ClassA object's lifecycle do you initialise stringA?
did that occur before you tried to use it in your ClassB object?
I would like to comment one thing you have high probability of RetainLoop, while ClassA retains ClassB and ClassB retains ClassA. When do they release?
Second thing, in:
ClassA.m:
stringA = [NSString stringWithString:webView.request.URL.absoluteString];
change to:
self.stringA = [NSString stringWithString:webView.request.URL.absoluteString];
while object returned by [NSString stringWithString:] is set to autorelease, and you need to retain it to be sure that you have valid instance of string.
Please provide more code.