Objective-C: Assigning the value of a static variable to an instance variable - objective-c

I essentially want to give each instance of a class a unique id.
So, I created a static integer. I increment it each time a new object is created and then assign the value of the static variable to an ivar. But clearly I don't understand something because, let's say I create three objects, "thisPageNumber" (which is the instance variable) is always 3 no matter which object I reference.
More information:
This class creates a number of "Page" objects. I'd like each page to know it's page number so that it can display the correct page art as well as perform a number of other various actions.
.h partial code:
#interface Page : UIViewController
{
NSNumber *thisPageNumber;
UIImageView *thisPageView;
UIImageView *nextPageView;
UIImageView *prevPageView;
UIImageView *pageArt;
}
.m partial code:
#implementation Page
static int pageCount = 0;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
pageCount++;
thisPageNumber = pageCount;
}
return self;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
CGRect defaultFrame = CGRectMake(0.0, 0.0, 1024.0, 768.0);
if (thisPageView == nil) {
thisPageView = [[UIImageView alloc]
initWithImage:[UIImage
imageNamed:[NSString stringWithFormat:#"Page%i.png", [thisPageNumber intValue]]]];
thisPageView.frame = defaultFrame;
[self.view addSubview:thisPageView];
}
if (nextPageView == nil && [thisPageNumber intValue] < BOOK_PAGE_COUNT) {
nextPageView = [[UIImageView alloc]
initWithImage:[UIImage
imageNamed:[NSString stringWithFormat:#"Page%i.png", [thisPageNumber intValue]+1]]];
nextPageView.frame = defaultFrame;
[self.view addSubview:nextPageView];
}
if (prevPageView == nil && [thisPageNumber intValue] > 1) {
prevPageView = [[UIImageView alloc]
initWithImage:[UIImage
imageNamed:[NSString stringWithFormat:#"Page%i.png", [thisPageNumber intValue]-1]]];
prevPageView.frame = defaultFrame;
[self.view addSubview:prevPageView];
}
}

I'm not sure why the compiler didn't complain, but part of your problem is here:
thisPageNumber = pageCount;
NSNumber is an object. To set it to the current pageCount value, use
thisPageNumber = [[NSNumber alloc] initWithInt:pageCount];

Why don't you just use self as the unique ID? It's unique.

Related

Why isn't my variable preserved in drawRect?

Im trying to have an nsview that takes a custom object as an argument, then draws out some text fields based on that object.
-(instancetype)initWithFrame:(NSRect)frameRect parent:(id)parent item:(TempObj*)item{
self = [super initWithFrame:frameRect];
if (self){
textDelegate = parent;
myObject = item;
}
return self;
}
But by the time it reaches the drawRect, the myObject variable is nil.
- (void)drawRect:(NSRect)dirtyRect {
if (myObject != nil){
NSTextField* title = [[NSTextField alloc]initWithFrame:CGRectMake(textRoot.x, textRoot.y-20, 200, 20)];
title.stringValue = [myObject getName];
title.backgroundColor = [NSColor yellowColor];
[self addSubview:title];
NSLog(#"here");
}else{
NSLog(#"broken");
}
}
The view is initialized in another class with:
_inventoryItemView = [[InventoryItemView alloc]initWithFrame:_inventoryItemView.frame parent:self item:testObj];
Is there some way for me to maintain the variable, or is there something with the scope I am missing?

nsmutabledictionary returning null when accessed outside of class

I have searched around a bit and not found an answer to my question. I am a beginner to objective-c and I am currently experimenting around with dictionaries. I have a class called "SETestBank" that creates 3 dictionaries of images and then adds them to a large dictionary. I am doing it this way because down the line I may add more smaller dictionaries. I've created a specific "accessBank" method to pull objects out via other classes.
SETestBank.m
#import "SETestBank.h"
#implementation SETestBank
#synthesize mathBankA, mathBankB, mathBankC, mathTest;
- (id)init
{
[self createBankA];
[self createBankB];
[self createBankC];
[self createTest];
return 0;
}
- (NSMutableDictionary *)createBankA
{
mathBankA = [[NSMutableDictionary alloc] init];
for (int i=0; i < 11; i++) {
NSString *aKey = [NSString stringWithFormat:#"%da", i];
NSString* imageName = [NSString stringWithFormat:#"%da.png",i];
[mathBankA setObject:imageName forKey:aKey];
NSLog(#"%#", aKey);
}
return mathBankA;
}
//same occurs to generate bankB and bankC
- (NSMutableDictionary *)createTest
{
mathTest = [[NSMutableDictionary alloc] init];
[mathTest addEntriesFromDictionary:mathBankA];
[mathTest addEntriesFromDictionary:mathBankB];
[mathTest addEntriesFromDictionary:mathBankC];
return mathTest;
}
- (NSString *)accessBank:(NSString *)accessor
{
NSString *img = [mathTest objectForKey:accessor];
return img;
}
#end
now this code seems to work fine. The dictionaries are created and console logs display the correct keys and object filenames (the images are all in the project and properly named)
However, when I access it in my view controller and try to apply an image to a UIImageView I get nothing.
SEViewController:
- (void)viewDidLoad
{
SETestBank *mathTest = [[SETestBank alloc] init];
UIImage *img = [UIImage imageNamed:[mathTest accessBank:#"1a"]];
NSString *test = [mathTest accessBank:#"1a"];
NSLog(#"%#", test);
[imageView setImage:img];
[self.view addSubview:imageView];
[super viewDidLoad];
}
the log here simply returns null along with a "CUICatalog: Invalid asset name supplied: (null), or invalid scale factor: 1.000000" error which I gather is from trying to assign null to an image. I'm stumped on this one. If I hardcode the image to display "1a.png" rather than trying to access it by key it works fine but that is not what I'm trying to accomplish. imageView is connected to a UIImageView in storyboard and the view controller is set to use SEViewController as it's class.
Thanks for any help!
In the init method, you return a 0, which means nothing (nil)
- (id)init
{
[self createBankA];
[self createBankB];
[self createBankC];
[self createTest];
return 0;
}
Change this to
- (id)init
{
if (self = [super init]) {
[self createBankA];
[self createBankB];
[self createBankC];
[self createTest];
}
return self;
}
may solve your problem.
Your init in SETestBank is returning 0, so your mathTest object is nil when you do
SETestBank *mathTest = [[SETestBank alloc] init];

Add image to UISegmentedControl from another controller

MainViewController contains UISegmentedControl with 3 segments.
SliderSubViewController contains a UISlider and -(void) sliderValueChanged:(UISlider*)sender
I want to add a code like this in SliderSubViewController.m but I'm stuck on how to access the UISegmentedControl and add an image:
- (void)viewDidLoad
{
[super viewDidLoad];
mainController = [[MainViewController alloc] initWithNibName:nil bundle:nil];
[minPrisSlider addTarget:self
action:#selector(sliderValueChanged:)
forControlEvents:UIControlEventValueChanged];
- (void)sliderValueChanged:(UISlider*)sender
{
NSUInteger index = (NSUInteger)(minPrisSlider.value + 0.5); // Round the number.
[minPrisSlider setValue:index animated:NO];
int progressAsInt =(int)(minPrisSlider.value + 0.5f);
NSString *newText =[[NSString alloc] initWithFormat:#"%d,-",progressAsInt];
minPrisText.text = newText;
if (minPrisSlider.value != 70) {
/*mainController.segmentedControl add main bundle image named "CheckboxChecked.png"
to current segment*/
}
}
If you have added SliderViewController as subview on MainViewController, One approach you can try is to just declare object of MainViewController in SliderViewController write #property and #synthesize, dont allocate it and while adding SliderView as subview just assign it as
sliderviewcontrollerObject.mainViewControllerObject = self;
now you can access segmentedControl from sliderview ass self.mainViewControllerObject.segmentedbar
Also you can try delegate approach.

Singleton not updating variable immediately

I have a singleton here is the header file:
#import <Foundation/Foundation.h>
#interface Shared : NSObject
{
NSString *messages;
}
#property (nonatomic, retain) NSString *messages;
+ (Shared*)sharedInstance;
#end
Here is the implementation:
#import "Shared.h"
static Shared* sharedInstance;
#implementation Shared
#synthesize messages;
+ (Shared*)sharedInstance
{
if ( !sharedInstance)
{
sharedInstance = [[Shared alloc] init];
}
return sharedInstance;
}
- (id)init
{
self = [super init];
if ( self )
{
messages = [[NSString alloc] init];
}
return self;
}
#end
The problem is when the I use
[Shared sharedInstance].messages = someVariable;
I can use
NSLog([Shared sharedInstance].messages);
and it shows the right output, but when i check from another class, NSLog doesn't show any output. I have the NSLog in the viewDidLoad method of another class, so when I click a button to go to the next view, it should output the value of the string, but it only works the second time. If the variable is set to dog, first it outputs nothing, then when I close the view and try again, it outputs dog. however, if I then change the variable to cat, it will output dog, and on the next attempt, output cat. I want it to update immediately, rather than remain one behind all the time.
EDIT: Here's the code from the other classes
This particular section is from a view controller class in the method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//Omitted, just preparing the DB, and emptying the array.
if ([db open])
{
FMResultSet *s = [db executeQueryWithFormat:#"SELECT ShabadID FROM Shabad WHERE Gurmukhi LIKE %#", currentLine];
while ([s next])
{
lineID = [s intForColumn:#"ShabadID"];
}
s = [db executeQueryWithFormat:#"SELECT Gurmukhi, ShabadID FROM Shabad WHERE ShabadID LIKE %i", lineID];
while ([s next])
{
//NSLog([s stringForColumn:#"Gurmukhi"]);
[paragraphArray addObject:[s stringForColumn:#"Gurmukhi"]];
}
Text = #"";
for (int i = 0; i<[paragraphArray count]; i++)
{
Text = [Text stringByAppendingFormat:#"%#\n", [paragraphArray objectAtIndex:i]];
}
[Shared sharedInstance].messages = Text;
}
Then in the another class, where I want the text to appear, in the viewDidLoad method,
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog([Shared sharedInstance].messages);
UITextView *myUITextView = [[UITextView alloc] initWithFrame:CGRectMake(0,30,310,450)];
myUITextView.text = [Shared sharedInstance].messages;
myUITextView.textAlignment = NSTextAlignmentCenter;
myUITextView.textColor = [UIColor blackColor];
myUITextView.font = [UIFont fontWithName:#"GurbaniLipiLight" size:24];
[myUITextView setBackgroundColor:[UIColor clearColor]];
myUITextView.editable = NO;
myUITextView.scrollEnabled = YES;
[ScrollerView addSubview:myUITextView];
}
Sure the NSLog doesn't show up right, but neither does the text in the textview, it does the same thing the NSLog does.
There is an assumption here about what order things happen in that's not quite right. Assuming there's a segue involved in this, didSelectRowAtIndexPath: is called after the new view controller is prepared but before it's displayed. Moving code to viewWillAppear: or viewDidAppear: delays execution until after the calling controller has set new data.
The other approach for communication between controllers that use a segue, is to use prepareForSegue: in the first controller to set data that the second controller needs. That way it should be available when the view is loaded.

UIImageView added to an NSArray doesn't respond

I am fairly new to Objective-C, this is the first time I really don't know what to do.
I have a class - Parser - which creates UIImageViews, inits them with images and adds them to the UIView. The class also adds these UIImageViews to NSMutableArray - imgArray, which is a property of another class - Page.
Then, on the click of a button, I call the Page class from a Manager class, loop through the imgArray and try to set a new images for the UIImageViews in the array.
It doesn't work. Actually nothing I do to the UIImageViews doesn't work.
I try [img removeFromSuperView], [img setHidden:YES] and more. It doesn't response.
Here I declare the Array property in Page:
#property (nonatomic, retain) NSMutableArray *imgArray;
Here is the code from Parser where I create the image and add it to the array:
UIImageView *img = [[UIImageView alloc] initWithFrame: frame];
NSString *name = [c imageSource];
[img setImage: [UIImage imageFromBook: name]];
[view addSubview: img];
[c setImage:img];
if (!page.imgArray)
{
page.imgArray = [[NSMutableArray alloc] init];
}
[page.imgArray addObject:img];
[img release];
Here is the loop code from the Manager:
- (void) set3D:(bool)is3D
{
Page *page = [[DataManager data] currentPage];
int count = [page.imgArray count];
for (int i = 0; i < count; i++)
{
UIImageView *img = [page.imgArray objectAtIndex:i];
[img setImage:[UIImage imageNamed:image3DSource]];
}
}
Thanks in advance for any help!
There is no need to store the UIImageView's in an array.
When the UIImageView's are created, you can tag them with an arbitrary number, like.
#define K_MIN_IMGV 100
#define K_MAX_IMGV 120
- (void) setupViews
{
for (NSInteger count = K_MIN_IMGV; count < K_MAX_IMGV; ++count)
{
UIImageView *imgV = // create image view, set properties
imgV.tag = count; // tag the views for easy retrieval later
...
[mainView addSubview: imgV]; // add subviews
[imgV release], imgV = nil; // mainView now manages, release our allocation
}
}
// how to set new images
- (void) setupNewImages
{
for (NSInteger count = K_MIN_IMGV; count < K_MAX_IMGV; ++count)
{
UIImageView *imgV = (UIImageView *) [mainView viewWithTag: count]; // retrieve imageView
[imgV setImage: newImage]; // set new image
}
}
// To remove the imageView, you can use
UIImageView *imgV = (UIImageView *) [mainView viewWithTag: 123];
[imgV removeFromSuperview];
Have you tried to enumerate through the array using:
for(UIImageView* imageView in page.imgArray)
{
//Do code
}
This will tell you if there any imageViews in page.imgArray.
How are you adding objects to NSMutableArray and how are you initialising your NSMutableArray.
I remember having a problem adding objects to NSMutableArray but setting my init to solved this:
NSMutableArray* mutableArray = [NSMutableArray array];
Also what properties have you set on imgArray in page? Are you retaining the values?
Need to see more code to gain a fuller understanding.