Moving data from 1 class to another - same app - objective-c

Need real help here!!!
I am trying to use data created in 1st class within the 2nd class. I have been searching Youtube and StackOverflow for over 1 week. Every time I think I am close, there is some element missing that I can not grasp. My latest attempt came from this site published in 2011 (Passing Data between classes objective-c) and while the application compiles, I can not see the data in the 2nd class.
More specific. I am using 2 classes because the data is gathered in groups (1st class) selected by the user and will be displayed on-screen in a table within the 2nd class. There are 6 NSMutable Arrays from the source passing to 6 different in the 2nd class. I will continue to try to solve, but I could use help.
Here is what I have devised from the 2011 article:
1st class .h code(partial):
#import <Cocoa/Cocoa.h>
#import <Foundation/Foundation.h>
#import "ReportsOutput.h"
//#class AppDelegate;
#class ReportsOutput;
#interface ReportsClass : NSWindowController<NSApplicationDelegate,NSMenuDelegate,NSWindowDelegate>{
ReportsOutput *ro;
//Shared Data arrays
NSMutableArray *tblYrScott;
NSMutableArray *tblYrExt;
NSMutableArray *tblYrYear;
NSMutableArray *tblYrType;
NSMutableArray *tblYrPrice;
NSMutableArray *tblYrDescription;
...... added code
#property(nonatomic,retain)NSMutableArray *tblYrScott;
#property(nonatomic,retain)NSMutableArray *tblYrExt;
#property(nonatomic,retain)NSMutableArray *tblYrType;
#property(nonatomic,retain)NSMutableArray *tblYrYear;
#property(nonatomic,retain)NSMutableArray *tblYrPrice;
#property(nonatomic,retain)NSMutableArray *tblYrDescription;
1st class .m code:
- (IBAction)btnShowDataOutput:(id)sender {
//pass data from Reports Class to Report Output Class
ReportsOutput *objReportsOutput = [[ReportsOutput alloc]init];
[objReportsOutput.tblScott setArray: tblYrScott];
[objReportsOutput.tblExt setArray:tblYrDescription];
[objReportsOutput.tblYear setArray:tblYrYear];
[objReportsOutput.tblType setArray:tblYrType];
[objReportsOutput.tblDescription setArray:tblYrDescription];
// open Reports Output Window
if (ro == nil){
ro = [[ReportsOutput alloc] initWithWindowNibName:#"ReportsOutput"];
}
[ro showWindow:nil];
}
2nd class .h code:
#import <Cocoa/Cocoa.h>
#import "ReportsClass.h"
#interface ReportsOutput : NSWindowController{
//shared data arrays
NSMutableArray *tblScott;
NSMutableArray *tblExt;
NSMutableArray *tblYear;
NSMutableArray *tblType;
NSMutableArray *tblPrice;
NSMutableArray *tblDescription;
}
#property(nonatomic,strong) NSMutableArray *tblScott;
#property(nonatomic,strong) NSMutableArray *tblExt;
#property(nonatomic,strong) NSMutableArray *tblYear;
#property(nonatomic,strong) NSMutableArray *tblType;
#property(nonatomic,strong) NSMutableArray *tblPrice;
#property(nonatomic,strong) NSMutableArray *tblDescription;
#end
2nd class .m code:
#import "ReportsOutput.h"
//#import "ReportsClass.h"
#interface ReportsOutput ()
#end
#implementation ReportsOutput
#synthesize tblScott;
#synthesize tblExt;
#synthesize tblType;
#synthesize tblPrice;
#synthesize tblYear;
#synthesize tblDescription;
- (void)windowDidLoad {
[super windowDidLoad];
}
-(void)awakeFromNib{
[self dataCheck];
}
-(void)dataCheck{
int a;
for (a=0; a<[self.tblScott count]; a++){
NSLog(#"#i,%d :%#: %#: %#: %#: %#: %#",a,[tblScott objectAtIndex:a],[tblExt objectAtIndex:a],[tblYear objectAtIndex:a],[tblType objectAtIndex:a],[tblPrice objectAtIndex:a],[tblDescription objectAtIndex:a]);
}
}

In btnShowDataOutput, you create objReportsOutput, but that object goes away as soon as the method ends. You don't need to create objReportsOutput. Instead, set the properties directly on the ReportsOutput window controller:
if (ro == nil){
ro = [[ReportsOutput alloc] initWithWindowNibName:#"ReportsOutput"];
}
ro.tblScott = self.tblYrScott
ro.tblExt = self.tblYrExt
ro.tblYear = self.tblYrYear
ro.tblType = self.tblYrType
ro.tblDescription = self.tblYrDescription
[ro showWindow:nil];

Related

objective-c: Using NSManagedObject for saving data with CoreData

Is it possible to extend an derived class from NSManagedObject? I'm asking this because I tried to do it. My entity looks like this:
So this means a class similar to the following code should be generated:
#import <Foundation/Foundation.h>
#interface Player : NSManagedObject
#property (nonatomic, copy) NSNumber* orderNumber;
#property (nonatomic, copy) NSString *name;
#end
.m file
#import "Player.h"
#implementation Player
#dynamic name, orderNumber;
#end
This two variables are saved to the SQLite database.
Now since I need some additional variables for the player I just added them to the class. It still worked.
#import "Player.h"
#implementation Player
#dynamic name, orderNumber;
- (id) init
{
self = [super init];
if (self != nil)
{
[self reset];
}
return self;
}
#synthesize isStillInGame = _isStillInGame;
- (void) reset
{
_isStillInGame = TRUE;
}
- (void) setOutOfGame
{
_isStillInGame = FALSE;
}
#end
But now when I change the isStillInGame bool, all instances of the Player Class are changed. Is this normal or do I have an error in my code?
A second question I can't answer is, why I can't access the object variables while debugging. When I try to watch an Player instance variable I just see this:
Is it possible to see more?

My own method isn't being found by the compiler

I recently started learning Objective-C and Cocos-2D. I tried to define my own method for automating the creation of sprites.
I added my own class where I'll create other automation methods as well. Anyhow my .h file looks like this:
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#interface ActionsClass : CCNode {
}
#property (nonatomic, strong) CCSprite* createSprite;
#property (nonatomic, strong) CCSprite* spriteName;
#property (nonatomic, strong) NSString* pngName;
#property (nonatomic) CGPoint* spriteCoordinate;
- (CCSprite *)createSprite: (CCSprite *)spriteName: (NSString *)pngName: (CGPoint *)spriteCoordinate;
#end
And the .m is:
#import "ActionsClass.h"
#implementation ActionsClass
#synthesize createSprite = _createSprite;
#synthesize spriteName = _spriteName;
#synthesize pngName = _pngName;
#synthesize spriteCoordinate = _spriteCoordinate;
- (CCSprite *)createSprite: (CCSprite *)spriteName: (NSString *)pngName: (CGPoint *)spriteCoordinate
{
if (!_createSprite)
{
_createSprite = [[CCSprite alloc] init];
_spriteName = [CCSprite spriteWithFile:_pngName];
_spriteName.position = ccp(_spriteCoordinate->x, _spriteCoordinate->y);
[self addChild:_spriteName];
}
return _createSprite;
}
#end
In the main .m file where I want to call the method:
[self createSprite: saif: #"saif.png": ccp(100,100)];
This would give the warning that xcode didn't find the instance method createSprite and defaults it to id
Thanks a lot and sorry if the font or the formatting of the question aren't super neat.
Your method declaration is wrong, so you wont be able to call it.
It should be:
- (CCSprite *)createSprite:(CCSprite *)spriteName pngName:(NSString *)pngName coord:(CGPoint *)spriteCoordinate;
And called like:
[self createSprite:someSprite pngName:somePNGName coord:someCoord];
Edit: I didn't see that you were trying to call this from another class. To do that you will need to import the ActionsClass header file, and call this method on an instance of ActionsClass, e.g.
ActionsClass *actionsClassObject = [[ActionsClass alloc] init];
[actionsClassObject createSprite:someSprite pngName:somePNGName coord:someCoord];

EXC_BAD_ACCESS when synthesizing a 'global' object

this is a follow-up question to my last one here: iOS: Initialise object at start of application for all controllers to use .
I have set my application up as follows (ignore the DB Prefix):
DBFactoryClass // Built a DataManaging Object for later use in the app
DBDataModel // Is created by the factory, holds all data & access methods
DBViewControllerA // Will show some of the data that DBDataModel holds
moreViewControllers that will need access to the same DBDataModel Object
i will go step by step through the application, and will then in the end post the error message i get when building.
AppDelegate.h
#import "DBFactoryClass.h"
AppDelegate.m
- (BOOL)...didFinishLaunching...
{
DBFactoryClass *FACTORY = [[DBFactoryClass alloc ]init ];
return YES;
}
DBFactoryClass.h
#import <Foundation/Foundation.h>
#import "DBDataModel.h"
#interface DBFactoryClass : NSObject
#property (strong) DBDataModel *DATAMODEL;
#end
DBFactoryClass.m
#import "DBFactoryClass.h"
#implementation DBFactoryClass
#synthesize DATAMODEL;
-(id)init{
self = [super init];
[self setDATAMODEL:[[DBDataModel alloc]init ]];
return self;
}
#end
ViewControllerA.h
#import <UIKit/UIKit.h>
#import "DBDataModel.h"
#class DBDataModel;
#interface todayViewController : UIViewController
#property (strong)DBDataModel *DATAMODEL;
#property (weak, nonatomic) IBOutlet UILabel *testLabel;
#end
ViewControllerA.m
#import "todayViewController.h"
#implementation todayViewController
#synthesize testLabel;
#synthesize DATAMODEL;
- (void)viewDidLoad
{
todaySpentLabel.text = [[DATAMODEL test]stringValue];
}
#end
DBDataModel.h
#import <Foundation/Foundation.h>
#interface DBDataModel : NSObject
#property (nonatomic, retain) NSNumber* test;
#end
DBDataModel.m
#import "DBDataModel.h"
#implementation DBDataModel
#synthesize test;
-(id)init{
test = [[NSNumber alloc]initWithInt:4];
return self;
}
#end
when i build it, i get the following error: EXC_BAD_ACCESS in this line:
#synthesize DATAMODEL;
of DBFactoryClass.m
What #synthesize does is to automatically generate implementations of the accessors for a property. EXC_BAD_ACCESS there means that you're accessing garbage when one of the accessors is executed.
That's probably happening here:
[self setDATAMODEL:[[DBDataModel alloc]init ]];
Make sure that DBDataModel's implementation of init actually returns a legitimate object.
As far as I can tell, your DBFactoryClass class is never stored anywhere, and therefore released right after the allocation if you use ARC (Since you use the strong keyword I assumed you do).
- (BOOL)...didFinishLaunching... {
DBFactoryClass *FACTORY = [[DBFactoryClass alloc ]init ];
// If you use ARC this might be released right afterwards
return YES;
}
If you want the factory to be a singleton, use something like this
+ (id)sharedInstance {
static dispatch_once_t once;
static MyFoo *instance;
dispatch_once(&once, ^{
instance = [[self alloc] init];
});
return instance;
}

referencing an Mutable array from ClassA to Class B

could someone help me reference an array from a different class.
here is ClassA.h
#interface ClassA : UIViewController <MKMapViewDelegate> {
NSMutableArray *theArray;
}
#property (nonatomic, retain) NSMutableArray *theArray;
-(NSMutableArray *) pleaseReturnTheArray;
#end
ClassA.m
#import "ClassA.h"
#implementation ClassA
#synthesize theArray;
...
-(NSMutableArray *) pleaseReturnTheArray {
return theArray;
}
and here is ClassB.m (i want to reference ClassA array, i have #import "MapView.h" into this class, this is a different view that gets pushed onto the screen)
- (void)viewDidLoad {
[super viewDidLoad];
//first test
ClassA *firstTest = [[ClassA alloc] init];
NSMutableArray *firstTestArray = [firstTest.theArray mutableCopy];
NSLog(#"first test - %#", firstTestArray);
//second test
NSMutableArray *secondTestArray = [firstTest pleaseReturnTheArray];
NSLog(#"second Test - %#", secondTestArray);
...
the result in NSLog i get is ...
first test - (null)
second Test - (null)
I am sure i have used one of these methods before and it has worked fine. Is it something to do with the fact that ClassB is a different view pushed by a tab bar controller?
any help would be appreciated.
Chris
My initial guess here is that you are not initializing theArray to a real array in your init method of ClassA. By default it will be nil. So the mutableCopy will also be nil as is shown in your output. Or perhaps adding this line of code after allocating firstTest would help:
firstTest.theArray = [NSArray arrayWithObjects:#"A",#"B",nil];
Also the pleaseReturnTheArray method is redundant with the theArray getter. You might as well write the following line of code instead:
NSMutableArray *secondTestArray = firstTest.theArray;
Note that because you are taking a mutable copy for firstTestArray, firstTestArray and secondTestArray will be equal but they will not be the same arrays. That means that if you add something in firstTestArray it won't show up in secondTestArray and vice versa.

How do I access my array from my table data source?

I am starting my first Cocoa Project. And I have a serious (for me) but maybe easy problem (for you) to solve and I need some direction where to start.
The short description: I have built a class "PortConnection.h" who writes all ports found by an external class (AMSerial.h) into an array when the function -listPorts is called. Here is the code for the PortConnection.h
#import <Cocoa/Cocoa.h>
#import "AMSerialPortList.h"
#import "AMSerialPortAdditions.h"
#import "AMSerialPort.h"
#interface PortConnection : NSObject {
#private
AMSerialPort *port;
NSMutableArray *portArray;
}
- (void)listDevices;
#property (nonatomic, retain) NSMutableArray *portArray;
#property (nonatomic, retain) AMSerialPort *port;
#end
and following the PortConnection.m
#import "PortConnection.h"
#import "AMSerialPortList.h"
#import "AMSerialPortAdditions.h"
#import "AMSerialPort.h"
#implementation PortConnection
#synthesize portArray;
#synthesize port;
- (void)listDevices
{
// get an port enumerator
NSEnumerator *enumerator = [AMSerialPortList portEnumerator];
AMSerialPort *aPort;
while ((aPort = [enumerator nextObject]))
{
// Add Devices to Array
[portArray addObject:[aPort bsdPath]];
}
}
So far it is perfectly working.
Now my questions
I have implemented an tableView in the GUI for display the results of the method called above. This file is called "PortTableViewController.h" and is the datasource for my TableView.
Here is the .h file
#import <Foundation/Foundation.h>
#import "PortConnection.h"
#interface PortTableViewController : NSObject <NSTableViewDataSource> {
#private
IBOutlet NSTableView *portTableView;
}
#property (assign) IBOutlet NSTableView *portTableView;
#end
and here is the .m file:
#import "PortTableViewController.h"
#import "PortConnection.h"
#implementation PortTableViewController
#synthesize portTableView;
#pragma mark -
#pragma mark TableView Delegates
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{
PortConnection *portConnection = [[PortConnection alloc] init];
[portConnection listDevices];
return [portConnection.portArray count];
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{
??????? I DO NOT HAVE A CLUE HOW TO ACCESS THE ARRAY IN PORTCONNECTION.M CORRECTLY
}
#end
QUESTIONS:
1) When having a look on the TableViewDataSourceDelegates how do I access the filled portArray in the PortConnection.m class correctly. It doesn't seem to work the way I do it.
2) Do I have to create an Object from Portconnection.h every time I want to retrieve Data from it in a tableviewdelegate method?
I am really thankful for every kind of help! I want to learn something.. and I really appreciate your support! Thanks.. for question in order to help me, don't hesitate. I really appreciate it....
Thanks
Sebastian
A simple fix is to have your table view controller declare an instance variable that holds a PortConnection instance. This instance is created and sent -listDevices in -init, it is used by all methods in your table view controller (which means that all methods refer to the same PortConnection instance), and released in -dealloc.
For example:
PortTableViewController.h
#import <Foundation/Foundation.h>
#import "PortConnection.h"
#interface PortTableViewController : NSObject <NSTableViewDataSource> {
#private
IBOutlet NSTableView *portTableView;
PortConnection *portConnection;
}
#property (assign) IBOutlet NSTableView *portTableView;
#end
PortTableViewController.m
#import "PortTableViewController.h"
#import "PortConnection.h"
#implementation PortTableViewController
#synthesize portTableView;
#pragma mark -
#pragma mark TableView Delegates
- (id)init {
self = [super init];
if (self) {
portConnection = [[PortConnection alloc] init];
[portConnection listDevices];
}
return self;
}
- (void)dealloc {
[portConnection release];
[super dealloc];
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{
return [portConnection.portArray count];
}
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{
return [portConnection.portArray objectAtIndex:row];
// or whatever behaviour provides an object value for the column/row
}
#end
If you don't want to create a field in every delegate you could create a static variable in PortConnection which holds the array. Initially the array is nil and on the first call to get the ports you create the list if needed.
In the implementation file:
static NSMutableArray *portArray;
+ (NSArray) listPorts {
if(portArray != nil)
return (NSArray *)portArray;
NSEnumerator *enumerator = [AMSerialPortList portEnumerator];
AMSerialPort *aPort;
portArray = [[NSMutableArray alloc] init];
while ((aPort = [enumerator nextObject])) {
// Add Devices to Array
[portArray addObject:[aPort bsdPath]];
}
}
This of course depends on how often the portArray will change, if it's often I would probably just generate it every time.
You could also do a getPortArray which calls generatePortArray if portArray is nil
You should only need a single PortConnection instance, but your table view controller will somehow need to know about it. It could be that the PortTableViewController creates and owns the PortConnection object, or it could be that some other object, like the app delegate or another controller creates it.
In the former case, it's trivial... the PortTableViewController creates the PortConnection instance, and therefore it has a reference to it and can access its portArray property at well.
In the latter case, things aren't much more complicated: the object that creates the PortController should give the PortTableViewController a pointer to the PortController. The PortTableViewController should then retain the PortController and stash the pointer in an instance variable so that it can access the portArray property as needed.