NSTableView add increasing number in row - objective-c

I'm trying to make NSTable view app with adding rows with two columns x and y. I want x column to be constant string but y column I want increase the initial number by 1 every time I press button add.
Here is my TableController implementation code
#implementation TableViewController
-(id)init {
self = [super init];
if (self) {
list = [[NSMutableArray alloc]init];
}
return self;
}
-(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [list count];
}
-(id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
Number *p = [list objectAtIndex:row];
NSString *identifier = [tableColumn identifier];
return [p valueForKey:identifier];
}
-(IBAction)add:(id)sender{
[list addObject:[[Number alloc] init]];
[tableView reloadData];
}
-(void) dealloc {
[super dealloc];
}
#end
and Number implementation file:
#implementation Number
#synthesize x;
#synthesize y;
-(id) init {
self=[super init];
if (self) {
int j;
x = 5;
y=2+j;
j++;
}
return self;
}
#end
Number .h file:
#import <Foundation/Foundation.h>
int j;
#interface Number : NSObject {
#private
int x,y;
}
#property int x,y,j;
#end
But the number in y column doesn't increase by 1 when I hit the add button. It seems to be reset every time I hit add button. Any help what am I doing wrong? Many thanks.

Declare j into .h file .
.f file:
int j;
int .m file :
-(id) init {
self=[super init];
if (self) {
x = 5;
y=2+j;
j++;
}
return self;
}

Related

Object loses reference

I have a IKImageBrowserView which has its own controller - BrowserController.h + .m
#interface BrowserController : NSWindowController{
NSMutableArray *_images;
}
#property (strong,nonatomic) IBOutlet IKImageBrowserView *imageBrowser;
-(void)addMultipleImages;
When I run the app for the first time, the staring image loads, but when I click a button to add other images and call a method from another class I don't get any results. I have noticed that my _imageBrowser loses the reference and becomes nil.
How could I solve this issue?
AppDelegate.m
#import "AppDelegate.h"
#import "BrowserController.h"
#implementation AppDelegate{
BrowserController *imageBrowserController;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
imageBrowserController = [BrowserController sharedManager];
}
- (IBAction)doSomething:(id)sender {
[imageBrowserController addMultipleImages];
}
#end
BrowserController.m
#import "BrowserController.h"
#interface myImageObject : NSObject
{
NSString *_path;
}
#end
#implementation myImageObject
/* our datasource object is just a filepath representation */
- (void)setPath:(NSString *)path
{
if(_path != path)
{
_path = path;
}
}
/* required methods of the IKImageBrowserItem protocol */
#pragma mark -
#pragma mark item data source protocol
/* let the image browser knows we use a path representation */
- (NSString *)imageRepresentationType
{
return IKImageBrowserPathRepresentationType;
}
/* give our representation to the image browser */
- (id)imageRepresentation
{
return _path;
}
/* use the absolute filepath as identifier */
- (NSString *)imageUID
{
return _path;
}
#end
#interface BrowserController ()
#end
#implementation BrowserController
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
// Drawing code here.
}
- (void)awakeFromNib{
myImageObject *p;
p = [[myImageObject alloc]init];
[p setPath:[[NSBundle mainBundle]pathForResource:#"Unknown" ofType:#"jpg"]];
_images = [[NSMutableArray alloc]init];
[_images addObject:p];
[self updateDataSource];
}
- (void)updateDataSource{
[_imageBrowser reloadData];
}
-(NSUInteger) numberOfItemsInImageBrowser:(IKImageBrowserView *)aBrowser{
return [_images count];
};
-(id)imageBrowser:(IKImageBrowserView *)aBrowser itemAtIndex:(NSUInteger)index{
return [_images objectAtIndex:index];
};
- (void)updateDatasource
{
[_imageBrowser reloadData];
}
- (void)addMultipleImages{
myImageObject *p;
p = [[myImageObject alloc]init];
[p setPath:[[NSBundle mainBundle]pathForResource:#"Unknown" ofType:#"jpg"]];
_images = [[NSMutableArray alloc]init];
[_images addObject:p];
[_images addObject:p];
[_images addObject:p];
[_imageBrowser reloadData];
}
+ (id)sharedManager {
static BrowserController *sharedMyManager = nil;
#synchronized(self) {
if (sharedMyManager == nil)
sharedMyManager = [[self alloc] init];
}
return sharedMyManager;
}
#end
There is some confusion as to the name of the class where you mention it's called ImageBrowserController at the start of your question and it looks like it's called BrowserController at the end of your question.
The issue is that you allocate _images in awakeFromNib which is never called given the class is created via the singleton pattern (sharedInstance) and not loaded from a .nib file.
Therefore move the code from awakeFromNib into init and dump awakeFromNib:
BrowserController.m:
- (id)init
{
self = [super init];
if (self) {
myImageObject *p = [[myImageObject alloc]init];
[p setPath:[[NSBundle mainBundle]pathForResource:#"Unknown" ofType:#"jpg"]];
_images = [[NSMutableArray alloc]init];
[_images addObject:p];
[self updateDataSource];
}
return self;
}
Further confusion: you have implemented an initWithFrame method. Why?

Filling a table with array with values from plist

I'm trying to populate a table view with an array with values from a plist. Everything looks right but when I compile it doesn't show any table what so ever. Any clues as to why?
#import "Person.h"
#implementation Person
-(void) setAge:(int)age{
_age = age;
}
-(int) age {
return _age;
}
-(void) setName:(NSString *)name{
_name = name;
}
-(NSString *) name{
return _name;
}
-(void) setJob:(NSString *)job{
_job = job;
}
-(NSString *) job{
return _job;
}
#interface Person : NSObject {
int _age;
NSString * _name;
NSString * _job;
}
-(void) setAge: (int) age;
-(int) age;
-(void) setName: (NSString *) name;
-(NSString *) name;
-(void) setJob: (NSString *) job;
-(NSString *) job;
-(NSString *) summaryString;
#end
#import <UIKit/UIKit.h>
#interface PeopleListViewController : UITableViewController
//Array to hold list of people
#property(nonatomic, strong) NSArray *people;
#end
#import "PeopleListViewController.h"
#import "Person.h"
#interface PeopleListViewController ()
#end
#implementation PeopleListViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *peopleArray = [NSMutableArray array];
NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:#"people" ofType:#"plist"]];
for(NSDictionary *dict in array){
Person *person = [[Person alloc] init];
person.job = [dict objectForKey:#"name"];
person.age = [[dict objectForKey:#"age"] intValue];
person.job = [dict objectForKey:#"job"];
[peopleArray addObject:person];
}
self.people = peopleArray;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
return 15;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text =
[[self.people objectAtIndex:indexPath.row] objectForKey:#"name"];
return cell;
}

Casting in Objective-C does not work as expected

I am new to programming with Objective-C and Stackoverflow, and I need some help.
I'm trying to get an object from a NSMutableArray and check one of its internal properties. I figured the best way to do this is by doing the following cast:
GenericRoom *room = (GenericRoom*)[myRooms objectAtIndex: currentIndex + side];
if (room.myType == EMPTY) {
return YES;
}
The problem is that when I create a class of type GenericRoom, your constructor already defines myType as EMPTY. When I insert the instances in NSMutrableArray, I changed to myType TAVERN this way:
NSMutableArray *myRooms = [[NSMutableArray alloc] initWithCapacity:15];
for (int i = 0: i <15: i + +) {
    GenericRoom tmpRoom * = [[GenericRoom alloc] initWithType: TAVERN];
    myRooms insertObject: tmpRoom atIndex i];
}
But when I do the cast that quote up there, it simply creates a new instance of the object GenericRoom, instead of copying the object inside NSMutableArray, making its result is always YES, my failing vereficação.
Is there any better way to solve this problem?
Thank you all.
EDIT: The complete code
GenericRoom.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
enum Rooms {
EMPTY, TAVERN, WARRIORGUILD, MAGEGUILD
}roomsType;
#interface GenericRoom : CCLayer {
CCSprite *mySprite;
enum Rooms myType;
}
#property (nonatomic, retain) CCSprite *mySprite;
#property enum Rooms myType;
#property int test;
- (id)initWithSprite: (NSString *)file;
- (id)initWithType: (enum Rooms)roomType;
#end
GenericRoom.m
#import "GenericRoom.h"
#implementation GenericRoom
#synthesize mySprite, myType, test;
-(id)init {
if (self = [super init]) {
}
return self;
}
-(id)initWithType: (enum Rooms) roomType {
if (self = [super init]) {
myType = roomType;
}
return self;
}
-(id)initWithSprite: (NSString *)file {
if (self = [super init]) {
mySprite = [CCSprite spriteWithFile:file];
[self addChild: mySprite];
}
return self;
}
#end
RoomManager.h
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "GenericRoom.h"
#import "RoomTavern.h"
#import "RoomEmpty.h"
enum Sides {
LEFT, RIGHT, UP, DOWN
}theSides;
#interface RoomManager : CCLayer {
CGSize size;
NSMutableArray *myRooms;
}
- (void) CreateRoom: (enum Rooms)roomType;
#end
RoomManager.m
#implementation RoomManager
-(id)init {
if (self = [super init]) {
size = [[CCDirector sharedDirector] winSize];
myRooms = [[NSMutableArray alloc] initWithCapacity:15];
for (int i = 0; i < 15; i++) {
GenericRoom *tmpRoom = [[GenericRoom alloc] initWithType:TAVERN];
tmpRoom.test = 10;
[myRooms insertObject:tmpRoom atIndex:i];
}
[self CreateRoom:TAVERN];
}
return self;
}
- (void) CreateRoom: (enum Rooms)roomType {
switch (roomType) {
case TAVERN:
{
//Create the Tavern Main Room
RoomTavern *tmpRoom = [[RoomTavern alloc] initWithSprite:#"room-hd.png"];
tmpRoom.mySprite.position = ccp(size.width/2,size.height/2);
[self addChild:tmpRoom];
[myRooms removeObjectAtIndex:8];
[myRooms insertObject:tmpRoom atIndex:8];
if ([self CheckAdjacentRooms:8 andSide:LEFT]) {
RoomEmpty *tmpEmptyRoom = [[RoomEmpty alloc] initWithSprite:#"roomToBuild-hd.png"];
tmpEmptyRoom.mySprite.position = ccp(tmpRoom.mySprite.position.x - tmpRoom.mySprite.contentSize.width, tmpRoom.mySprite.position.y);
[self addChild:tmpEmptyRoom];
[myRooms insertObject:tmpEmptyRoom atIndex:7];
}
break;
}
default:
break;
}
}
- (BOOL) CheckAdjacentRooms: (int)currentIndex andSide:(enum Sides)side {
int leftRightSide = 0;
if(side == LEFT)
leftRightSide = -1;
else if (side == RIGHT)
leftRightSide = 1;
GenericRoom *roomTmp = (GenericRoom *)[myRooms objectAtIndex:currentIndex + side];
if (roomTmp.myType == EMPTY) {
return YES;
}
else
return NO;
}
#end
To enhance #Dan F answer. Read this ...
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocObjectsClasses.html#//apple_ref/doc/uid/TP30001163-CH11-SW7
... what's nil messaging. Your locally declared myRooms variable hides your myRooms property (= instance variable). In other words, myRooms is nil. And what happens ...
GenericRoom *room = (GenericRoom*)[myRooms objectAtIndex: currentIndex + side];
Because of nil messaging rules, [myRooms objectAtIndex:...] returns nil, thus your room is set to nil.
if (room.myType == EMPTY) {
return YES;
}
And room.myType sends message myType to room object. And because room is nil, return value is 0 - enums does contain integer scalar values - this is the reason why it returns 0. And I assume that EMPTY is first element in your enum = has value 0. And 0 == 0 => returns YES even when your myRooms instance variable is nil.
If your code above is how it appears in your actual project, then the problem is you are re-declaring your myRooms object. When you write this line:
NSMutableArray *myRooms = [[NSMutableArray alloc] initWithCapacity:15];
you are creating a new locally-scoped object named myRooms that is lost when you exit the current scope (method, block, etc.)
What you need to do to fix this is simply remove the NSMutableArray * at the beginning of the line, and it will assign the newly allocated array to your property. Like so:
myRooms = [[NSMutableArray alloc] initWithCapacity:15];
Your initialiser seems to have some flaws, that might cause your issues.
// NOTE: `Rooms` instead of `enum Rooms`
- (id)initWithType:(Rooms)roomType
{
if (self = [super init])
{
// NOTE: accessor is used, otherwise the value is cleared when out of scope
self.myType = roomType;
}
return self;
}

Issue initializing an object of a custom class

I'm trying to make a custom HashTable for my program. Yes, I know there is already a HashTable class in Xcode, but for this case I have a custom one. It's supposed to be simple, but when I'm trying to use it in my view controller, the debugger shows its value to be "0x0", even after calling the initialization method. Here's the code:
//header file HashTable.h
#import <Foundation/Foundation.h>
#interface HashTable : NSObject
{
}
-(void)initWithLength:(int)capacity;
-(void)add:(NSObject*)object withName:(NSString*)name;
-(id)getObjectFromIndex:(int)index;
-(id)getObjectWithName:(NSString*)name;
#end
//main file HashTable.m
#import "HashTable.h"
#implementation HashTable
NSMutableArray* values;
NSMutableArray* markers;
-(id)initWithLength:(int)capacity //Apparently, this never gets called
{
self = [super init];
if (self)
{
values = [[NSMutableArray alloc] initWithCapacity:capacity];
markers = [[NSMutableArray alloc] initWithCapacity:capacity];
}
return self;
}
-(void)add:(NSObject*)object withName:(NSString*)name
{
[values addObject:object];
[markers addObject:name];
}
-(id)getObjectFromIndex:(int)index
{
return [values objectAtIndex:index];
}
-(id)getObjectWithName:(NSString*)name
{
for (int i = 0; i < [markers count]; i++)
{
if ([[markers objectAtIndex:i] isEqualToString:name]) {return [values objectAtIndex:i];}
}
return [NSObject new];
}
-(void)removeObjectFromIndex:(int)index
{
[values removeObjectAtIndex:index];
[markers removeObjectAtIndex:index];
}
-(void)removeObjectWithName:(NSString*)name
{
for (int i = 0; i < [markers count]; i++)
{
if ([[markers objectAtIndex:i] isEqualToString:name])
{
[values removeObjectAtIndex:i];
[markers removeObjectAtIndex:i];
return;
}
}
}
-(BOOL)isEmpty
{
return [values count] == 0;
}
-(void)dealloc
{
[values release];
[markers release];
[super dealloc];
}
#end
Then I have the segments of the view controller that uses HashTable:
//header file
#import <UIKit/UIKit.h>
#import "HashTable.h"
#interface Circuitry_LabViewController : UIViewController
{
HashTable* table;
}
#property(nonatomic, retain) HashTable* table;
#end
//main file
#import "Circuitry_LabViewController.h"
#implementation Circuitry_LabViewController
#synthesize table;
- (void)viewDidLoad
{
[table initWithLength:10];
[super viewDidLoad];
}
I can't see what I'm missing here. Can anyone help?
You meant to do this in -viewDidLoad:
table = [[HashTable alloc] initWithLength:10];
Something's telling me that you're doing it wrong.

Objective C - Create a multi-dimensional array with the dimensions specified at initialisation

I am trying to create a class where the width and height of a 2 dimensional array can be dynamically created at the point of initialisation with init parameters.
I have been looking through the web for hours and cannot find a way.
Using a standard C syntax [][] does not allow for a variable to be used to declare the array.
The mutable arrays within Objective C, in all examples I have seen, require the objects to be hard coded at the time of creation.
Is there a way of creating a 2 dimensional array within an object with parameters to define the sizes at the point of creation?
Hoping someone can tell me what I am missing...
You can do this quite easily by writing a category on NSMutableArray:
#interface NSMutableArray (MultidimensionalAdditions)
+ (NSMutableArray *) arrayOfWidth:(NSInteger) width andHeight:(NSInteger) height;
- (id) initWithWidth:(NSInteger) width andHeight:(NSInteger) height;
#end
#implementation NSMutableArray (MultidimensionalAdditions)
+ (NSMutableArray *) arrayOfWidth:(NSInteger) width andHeight:(NSInteger) height {
return [[[self alloc] initWithWidth:width andHeight:height] autorelease];
}
- (id) initWithWidth:(NSInteger) width andHeight:(NSInteger) height {
if((self = [self initWithCapacity:height])) {
for(int i = 0; i < height; i++) {
NSMutableArray *inner = [[NSMutableArray alloc] initWithCapacity:width];
for(int j = 0; j < width; j++)
[inner addObject:[NSNull null]];
[self addObject:inner];
[inner release];
}
}
return self;
}
#end
Usage:
NSMutableArray *dynamic_md_array = [NSMutableArray arrayOfWidth:2 andHeight:2];
Or:
NSMutableArray *dynamic_md_array = [[NSMutableArray alloc] initWithWidth:2 andHeight:2];
Here is another pure Objective C Version
#import foundation.h
#interface ZTwoDimensionalArray : NSObject{
#package
NSMutableArray* _array;
int _rows, _columns;
}
-(id) initWIthRows:(int)numberOfRows andColumns:(int) numberOfColumns;
-(id) getObjectAtRow:(int) row andColumn:(int)column;
-(void) setObject:(id) anObject atRow:(int) row andColumn:(int)column;
#end
#import "ZTwoDimensionalArray.h"
#implementation ZTwoDimensionalArray
-(id) initWIthRows:(int)numberOfRows andColumns:(int) numberOfColumns{
if (self = [super init]) {
_array = [NSMutableArray initWithCapacity:numberOfRows*numberOfColumns];
_rows = numberOfRows;
_columns = numberOfColumns;
}
return self;
}
-(id) getObjectAtRow:(int) row andColumn:(int)column{
return [_array objectAtIndex: row*_rows + column];
}
-(void) setObject:(id) anObject atRow:(int) row andColumn:(int)column{
[_array insertObject:anObject atIndex:row*_rows + column];
}
-(void) dealloc{
[_array release];
}
#end
Here's another way. Of course this is just for int but the code could easily be altered for other datatypes.
AOMatrix.h:
#import <Cocoa/Cocoa.h>
#interface AOMatrix : NSObject {
#private
int* matrix_;
uint columnCount_;
uint rowCount_;
}
- (id)initWithRows:(uint)rowCount Columns:(uint)columnCount;
- (uint)rowCount;
- (uint)columnCount;
- (int)valueAtRow:(uint)rowIndex Column:(uint)columnIndex;
- (void)setValue:(int)value atRow:(uint)rowIndex Column:(uint)columnIndex;
#end
AOMatrix.m
#import "AOMatrix.h"
#define INITIAL_MATRIX_VALUE 0
#define DEFAULT_ROW_COUNT 4
#define DEFAULT_COLUMN_COUNT 4
/****************************************************************************
* BIG NOTE:
* Access values in the matrix_ by matrix_[rowIndex*columnCount+columnIndex]
****************************************************************************/
#implementation AOMatrix
- (id)init {
return [self initWithRows:DEFAULT_ROW_COUNT Columns:DEFAULT_COLUMN_COUNT];
}
- (id)initWithRows:(uint)initRowCount Columns:(uint)initColumnCount {
self = [super init];
if(self) {
rowCount_ = initRowCount;
columnCount_ = initColumnCount;
matrix_ = malloc(sizeof(int)*rowCount_*columnCount_);
uint i;
for(i = 0; i < rowCount_*columnCount_; ++i) {
matrix_[i] = INITIAL_MATRIX_VALUE;
}
// NSLog(#"matrix_ is %ux%u", rowCount_, columnCount_);
// NSLog(#"matrix_[0] is at %p", &(matrix_[0]));
// NSLog(#"matrix_[%u] is at %p", i-1, &(matrix_[i-1]));
}
return self;
}
- (void)dealloc {
free(matrix_);
[super dealloc];
}
- (uint)rowCount {
return rowCount_;
}
- (uint)columnCount {
return columnCount_;
}
- (int)valueAtRow:(uint)rowIndex Column:(uint)columnIndex {
// NSLog(#"matrix_[%u](%u,%u) is at %p with value %d", rowIndex*columnCount_+columnIndex, rowIndex, columnIndex, &(matrix_[rowIndex*columnCount_+columnIndex]), matrix_[rowIndex*columnCount+columnIndex]);
return matrix_[rowIndex*columnCount_+columnIndex];
}
- (void)setValue:(int)value atRow:(uint)rowIndex Column:(uint)columnIndex {
matrix_[rowIndex*columnCount_+columnIndex] = value;
}
#end