I've got a problem at programming for iOS. Already looked for some similar problems but haven't found anything yet.
I'm creating at least 8 custom UIViews. As you can see in the appended code i'm running through a loop creating one instance per round. The reference of every object is on a different space in the memory but when i change a value in one object it only affects the object that has been created in the last loop-round (last created instance).
Any Ideas?
PadView.h:
#import <UIKit/UIKit.h>
#interface PadView : UIView {
}
- (void)setText:(NSString*)text;
#end
PadView.m:
#import "PadView.h"
#import "AVFoundation/AVFoundation.h";
#implementation PadView
AVAudioPlayer *player;
UILabel *label;
- (void)setText:(NSString*)text {
label.text = text;
}
- (void)initialize {
label = [[ UILabel alloc ] initWithFrame:CGRectMake(0.0, 93.0, 107.0, 13.0)];
label.backgroundColor = [UIColor clearColor];
label.font = [UIFont boldSystemFontOfSize:9];
label.textAlignment = UITextAlignmentCenter;
label.text = #"Empty";
[self addSubview:label];
[label release];
}
- (id) initWithCoder:(NSCoder *)aCoder {
if (self = [super initWithCoder:aCoder]) {
[self initialize];
}
return self;
}
- (id) initWithFrame:(CGRect)rect {
if (self = [super initWithFrame:rect]) {
[self initialize];
}
return self;
}
- (void)dealloc {
[super dealloc];
}
#end
Create the Objects:
NSMutableArray *pads = [[NSMutableArray alloc] initWithCapacity:8];
for (int i = 0; i < 8; i++) {
PadView *pad = [[PadView alloc] initWithFrame:CGRectMake(0.0, i*150, 107.0, 107.0)];
[padsView addSubview:pad];
[pads addObject:pad];
}
Call setText:
PadView *pad = [pads objectAtIndex:5];
[pad setText:#"test"];
Your variables:
AVAudioPlayer *player;
UILabel *label;
are defined in the #implementation block, so they are effectively global variables (in the C sense).
So basically, all your instances of PadView will change the same UILabel when you set its text property (which explains the behavior you are seeing).
I'm lacking some context, but it seems that you want label to be an instance variable instead (and I'd assume player as well). If that's the case, you need to declare them in the #interface block as follows:
#interface PadView : UIView {
AVAudioPlayer *player;
UILabel *label;
}
- (void)setText:(NSString*)text;
#end
pads is not initialized
NSMutableArray *pads = [[NSMutableArray alloc] initWithCapacity:8];
and you must release pad after adding as subview and to the array
By convention the class should be named PadView, not padView
edit
for(padView *pad in pads){
//manipulate each pad
}
//manipulate a certain pad
padView *pad = [pads objectAtIndex:5];
pad. //...
Related
Im making a program to draw the chart (which i keep in NSView class). However action & data I want to pass from NSViewController. So could you help me how to do it. I did try as bellow code however it doesn't work.
#implementation PlottingChart
#synthesize plotChartData;
- (void)drawRect:(NSRect)dirtyRect{
[super drawRect:dirtyRect];
[self drawChartGrid:plotChartData];
}
-(void)drawChartGrid:(NSMutableArray *)ChartData
{
//Drawing code here
}
#interface PlottingChart : NSView
#property (nonatomic, strong) NSMutableArray *plotChartData;
-(void)drawChartGrid:(NSMutableArray *)ChartData;
#end
#import "PlottingChart.h"
#interface ViewController :NSViewController<NSTableViewDataSource,NSTableViewDelegate>
{
PlottingChart *boxPlotChart;
}
- (IBAction)btnStart:(id)sender {
//trial draw chart
NSDictionary *dict1 = #{#"plot_Q1":#"180",#"plot_Q3": #"220", #"plot_Max":#"250", #"plot_Min":#"150", #"plot_Median":#"200"};
NSDictionary *dict2 = #{#"plot_Q1":#"190",#"plot_Q3": #"230", #"plot_Max":#"280", #"plot_Min":#"160", #"plot_Median":#"210"};
NSMutableArray *array = [NSMutableArray arrayWithObjects:dict1,dict2, nil];
boxPlotChart.plotChartData = array;
[boxPlotChart drawChartGrid:array];
boxPlotChart = [[PlottingChart alloc] initWithFrame:NSMakeRect(10, -50, 850, 360) ]; // x,y lenght,height
[self.view addSubview:boxPlotChart];
}
Finally I found the solution.
Add initWithFrame method into NSView.
- (id)initWithFrame:(NSRect)frame dataArray:(NSMutableArray *)dtArray;
{
self = [super initWithFrame:frame];
self.plotChartData = dtArray;
return self;
}
And initial this one in NSViewController.
boxPlotChart = [[PlottingChart alloc] initWithFrame:NSMakeRect(10, -50, 850, 360) dataArray:array ];
Today I'm facing a new problem:
I have a ViewController (Subclass of NSView) and another class (Subclass of NSObject) which, through an IBAction, try to call back the viewController to redraw its view using SetNeedsDisplay:YES.
The method to redraw the view (ViewController.m) is:
- (void) redrawView {
[self setNeedsDisplay:YES]
}
// With an NSLog i see that the method is called !
// Instead of self i tried even an outlet connected to the custom view.
}
What I'm doing to call the ViewController method through my other class is:
1) #import "ViewController.h"
2) into the IBAction i made a new istance of ViewController as:
ViewController *newIstanceOfViewController = [[ViewController alloc] init]
3) [newIstanceOfViewController redrawView]
The log show me that setNeedsDisplay is called but drawrect no ! Why ? I have forgotten to init or subview something ? Thanks
THE ORIGINAL CODE HERE (DIFFERENT NAME OF METHODS DUE TO LANGUAGE, SAME SYNTAX)
// Controller.h
#import <Cocoa/Cocoa.h>
#interface Controller : NSView {
IBOutlet NSView *tastierinoView;
}
- (void) aggiornaTastierinoView;
#end
// Controller.m
#import "Controller.h"
#implementation Controller
//Contatore numero volte disegno view
int contatore = 0;
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
tastierinoView = [[NSView alloc] init];
}
return self;
}
- (void) aggiornaTastierinoView { //THIS IS THE METHOD TO CALL REDRAW
[tastierinoView setNeedsDisplay:YES];
NSLog(#"Chiamo setneedsDisplay\n\n");
}
- (void)drawRect:(NSRect)dirtyRect
{
contatore++;
NSLog(#"La view รจ stata disegnata %d volte\n\n",contatore);
[super drawRect:dirtyRect];
// Drawing code here.
NSBezierPath* percorso = [NSBezierPath bezierPath];
[[NSColor cyanColor] set];
[percorso moveToPoint:NSMakePoint(150, 150)];
[percorso lineToPoint:NSMakePoint(250, 150)];
[percorso setLineWidth:5.0];
[percorso stroke];
}
#end
// ManipolatorePin.h
#import <Foundation/Foundation.h>
#interface ManipolatorePin : NSObject {
IBOutlet NSWindow *finestraPrincipaleWindow;
IBOutlet NSTextField *codiceTextField;
NSArray *coordinate_x;
NSArray *coordinate_y;
//L'array sotto riportato serve, tramite un ciclo for, a salvare il codice pin spezzato in singoli numeri che corrisponderanno al punto.
NSMutableArray *numeroAllaIndexArray;
}
- (IBAction)aggiornaTastierino:(id)sender;
#end
// ManipolatorePin.m
#import "ManipolatorePin.h"
#import "Controller.h"
#implementation ManipolatorePin
- (void)awakeFromNib {
coordinate_x = [[NSArray alloc] initWithObjects:#"150",#"50",#"150",#"250",#"50",#"150",#"250",#"50",#"150",#"250", nil];
coordinate_y = [[NSArray alloc] initWithObjects:#"50",#"150",#"150",#"150",#"250",#"250",#"250",#"350",#"350",#"350", nil];
numeroAllaIndexArray = [[NSMutableArray alloc] init];
NSLog(#"Array coordinate iniziallizato.\nTest:(%#) -> deve risultare \"50\"\n\n",[coordinate_x objectAtIndex:4]);
}
- (IBAction)aggiornaTastierino:(id)sender {
NSString *codiceString = [[NSString alloc] initWithFormat:[NSString stringWithFormat:#"%#",[codiceTextField stringValue]]];
NSLog(#"codiceTextField = %#", codiceString);
int lunghezzaCodiceString;
NSLog(#"Il codice risulta essere composto da (%d) numeri\n\n",[codiceString length]);
//Svuoto array
[numeroAllaIndexArray removeAllObjects];
for (lunghezzaCodiceString = 0; lunghezzaCodiceString < [codiceString length]; lunghezzaCodiceString++) {
//Compilo array (Ci provo ahah)
NSString *carattereDelCodiceStringInEsame = [[NSString alloc] init];
carattereDelCodiceStringInEsame = [codiceString substringWithRange:NSMakeRange(lunghezzaCodiceString,1)];
NSLog(#"Aggiungo il numero (%#) all'array 'numeroAllaIndexArray'",carattereDelCodiceStringInEsame);
[numeroAllaIndexArray addObject:carattereDelCodiceStringInEsame];
}
//DEBUG - DA QUI IN POI E' CANCELLABILE
NSLog(#"\n\nCiclo for termitato\nProcesso concluso con successo\n\n\nContenuto array:");
int conteggioArray;
for (conteggioArray = 0; conteggioArray < [numeroAllaIndexArray count] ; conteggioArray++ ) {
NSLog(#"index (%d) -> (%#)",conteggioArray,[numeroAllaIndexArray objectAtIndex:conteggioArray]);
NSLog(#"\n\n");
}
//FINE DEBUG
///////////////HERE THE INSTANCE TO CALL THE CONTROLLER
Controller *istanzaGestionaleController = [[Controller alloc] init];
[istanzaGestionaleController aggiornaTastierinoView];
}
#end
It sounds like you have two unrelated instances of ViewController. You need to call redrawView on the instance that actually has a view on the screen.
In your class (which is not the NSViewController), create a property like this:
#property (nonatomic, readwrite, weak) NSViewController *vc;
When the class is instantiated:
YourClass *yourInstance = [[YourClass alloc] init];
assign the value of vc:
yourInstance.vc = self; // self is your NSViewController instance
Then when you want to trigger a redraw, you pass the command to self.vc inside your other class.
I'm trying to write a little weightwatchers points calculator app for myself. I know you can just download one from the appstore but i am trying to learn objective-c and thought this would be a fairly easy first app. I just want to use text entered into a textbox and save it as a variable and use said variable to perform basic math with the intValues. I've tried using the 'text' property of UITextField with no luck, could someone help and tell me what i've done wrong here? well this is awkward...it seems i forgot to tell you what the problem is. i've included the errors i'm receiving on their corresponding lines. What i'm getting out of these errors is that i shouldn't be using the "NSString" to define my variables, maybe "int" instead?
.h file:
#import <UIKit/UIKit.h>
#class FirstViewController;
NSString*txtProtein = nil;
NSString *txtCarbs = nil;
NSString *txtFat = nil;
NSString *txtFiber = nil;
NSString *txtPoints = nil;
NSString *txtproteinCalc = nil;
NSString *txtcarbCalc = nil;
NSString *txtfatCalc = nil;
NSString *txtfiberCalc = nil;
#interface AppDelegate : NSObject
<UIApplicationDelegate> {
UIWindow *window;
FirstViewController
*viewController;
UITextField *protein;
UITextField *carbs;
UITextField *fat;
UITextField *fiber;
UITextView *points;
}
#property (nonatomic, retain)
IBOutlet UIWindow *window;
#property (nonatomic, retain)
IBOutlet FirstViewController *viewController;
#end
and the .m file:
#import "FirstViewController.h"
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize window;
#synthesize viewController;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Here is where all of the textboxes are defined.
//All of the strings are in the viewController.h
//This is the protein part
txtProtein = [[[UITextField alloc] initWithFrame:CGRectMake(10.0, 10.0, 50.0, 25.0)]; (expected identifier)
txtProtein.backgroundColor = [UIColor whiteColor]; (property "backgroundcolor" not found on object of type 'NSString')
txtProtein.placeholder = #"Protein"; (property "placeholder" not found on object of type 'NSString')
[viewController.view addSubview:txtProtein]; (property 'view' can not be found in forward class object "FirstViewController")
//This is the carbs part
txtCarbs = [[[UITextField alloc] initWithFrame:CGRectMake(30.0, 10.0, 50.0, 25.0)];
txtCarbs.backgroundColor = [UIColor whiteColor];
txtCarbs.placeholder = #"Carbs";
[viewController.view addSubview:txtCarbs];
//This is the Fat part
txtFat = [[[UITextField alloc] initWithFrame:CGRectMake(50.0, 10.0, 50.0, 25.0)];
txtFat.backgroundColor = [UIColor whiteColor];
txtFat.placeholder = #"Fat";
[viewController.view addSubview:txtFat];
//This is the Fiber
txtFiber = [[[UITextField alloc] initWithFrame:CGRectMake(70.0, 10.0, 50.0, 25.0)];
txtFiber.backgroundColor = [UIColor whiteColor];
txtFiber.placeholder = #"Fiber";
[viewController.view addSubview:txtFiber];
//Total Points
txtPoints = [[[UITextField alloc] initWithFrame: CGRectMake(150.0, 10.0, 50.0, 25.0)]autorelease];
txtPoints.backgroundColor = [UIColor greenColor];
txtPoints.editable = NO;
[viewController.view addSubview:txtPoints];
//Protein divided by 10.9375
txtproteinCalc = [txtProtein.text intValue] / [10.9375];
//Carbs divided by 9.2105
txtcarbCalc = [txtCarbs.text intValue] / [9.2105];
//Fat divided by 3.8889
txtfatCalc = [txtFat.text intValue] / [3.8889];
//Fiber divided by 12.5
txtfiberCalc = [txtFiber.text intValue] / [12.5];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(calculatePoints)
name:UITextFieldTextDidChangeNotification
object:nil];
//Add the view controller's view to the window and display
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
//Make keyboard show up in the Protein (The first) box
[txtProtein becomeFirstResponder];
return YES;
}
#pragma mark -
#pragma mark Memory management
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
/*
Free up as much Memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later/
*/
}
-(void)dealloc {
[txtProtein release];
[txtFiber release];
[txtFat release];
[txtCarbs release];
[txtPoints release];
[viewController release];
[window release];
[super dealloc];
}
#pragma mark -
#pragma mark Other Methods
-(void)calculatePoints {
NSLog(#"Calculating FoodTrakr Value...");
txtPoints.text = #"";
if (txtProtein.text.length > 0 && [txtProtein.text intValue]>0 && txtFiber.text.length >0 && [txtFiber.text intValue]>0 && txtFat.text.length >0 && [txtFat.text intValue]>0 && txtCarbs.text.length >0 && [txtCarbs.text intValue]>0
)
{
int Points = [txtproteinCalc.text intValue] + [txtcarbCalc.text intValue] + [txtfatCalc.text intValue] - [txtfiberCalc.text intValue];
txtPoints.text = [[NSNumber numberWithInt:points] stringValue];
}
}
#end
Thanks in advance for any help!
also, if you guys have any recommended books for learning objective c, i've done some reading but i know i obviously need to read up some more, if you could leave any suggestions that helped you learn that would be awesome. Thanks!
To be blunt, the posted code has a lot of serious issues. Let's start with the immediate compile errors.
You have:
txtProtein = [[[UITextField alloc] initWithFrame:CGRectMake(10.0, 10.0, 50.0, 25.0)]; (expected identifier)
txtProtein.backgroundColor = [UIColor whiteColor]; (property "backgroundcolor" not found on object of type 'NSString')
txtProtein.placeholder = #"Protein"; (property "placeholder" not found on object of type 'NSString')
[viewController.view addSubview:txtProtein]; (property 'view' can not be found in forward class object "FirstViewController")
The first line has one too many open brackets. The other major problem with this is you are creating a UITextField but you are assigning it to a variable for an NSString. Instead of txtProtein you should use your protein variable which has the property type. So the code should be:
protein = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10.0, 50.0, 25.0)];
protein.backgroundColor = [UIColor whiteColor];
protein.placeholder = #"Protein";
[viewController.view addSubview:protein];
You have the same issues repeated over and over in this code.
The next big issue is why is all of this code in your app delegate? Most, if not all, of this code belongs in the FirstViewController.m file. Your app delegate should not be responsible for setting up the view controller. Let the view controller set itself up.
Next, why do you have all of these global variables?
I suggest you find some good tutorials on Objective-C programming then some good tutorials on iOS app development.
I want to draw the text in an UITextField with a shadow. In order to do this, I have subclassed UITextField, and implemented the drawTextInRect: method as follows:
- (void)drawTextInRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
// Create shadow color
float colorValues[] = {0.21875, 0.21875, 0.21875, 1.0};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGColorRef shadowColor = CGColorCreate(colorSpace, colorValues);
CGColorSpaceRelease(colorSpace);
// Create shadow
CGSize shadowOffset = CGSizeMake(2, 2);
CGContextSetShadowWithColor(context, shadowOffset, 0, shadowColor);
CGColorRelease(shadowColor);
// Render text
[super drawTextInRect:rect];
}
This works great for when the text field is not editing, but as soon as editing begins, the shadow disappears. Is there anything I am missing?
Here is the code for following component
#interface AZTextField ()
- (void)privateInitialization;
#end
#implementation AZTextField
static CGFloat const kAZTextFieldCornerRadius = 3.0;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (!self) return nil;
[self privateInitialization];
return self;
}
// In case you decided to use it in a nib
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (!self) return nil;
[self privateInitialization];
return self;
}
- (void)privateInitialization
{
self.borderStyle = UITextBorderStyleNone;
self.layer.masksToBounds = NO;
self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowOffset = CGSizeMake(0.0f, 5.0f);
self.layer.shadowOpacity = 0.5f;
self.layer.backgroundColor = [UIColor whiteColor].CGColor;
self.layer.cornerRadius = 4;
// This code is better to be called whenever size of the textfield changed,
// so if you plan to do that you can add an observer for bounds property
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:kAZTextFieldCornerRadius];
self.layer.shadowPath = shadowPath.CGPath;
}
#end
Couple of things to consider:
You want to set borderStyle to none, otherwise you'll end up with
UIKit putting subviews into your textfield
Depending on the Xcode
version you might want to link QuartzCore and to #import
<QuartzCore/QuartzCore.h>
For more complex appearance you can still
use shadow properties of the layer and move the drawing code itself
into the drawRect: method, but jake_hetfield was right if you
override drawRect you don't want to call super, especially in the end
of the method
As for the text drawing (you can see that it sticks to
close to the component borders), you have a separate
drawTextInRect: and drawPlaceholderInRect: method that draws the
text and placeholder respectively
You can use UIColor method for
colors and call CGColor property, it makes code more readable and
easier to maintain
Hope that helps!
Inspired by #jake_hetfield answer I created a custom UITextField that uses an internal label to do the drawing, check it out:
ShadowTextField .h file
#import <UIKit/UIKit.h>
#interface ShadowTextField : UITextField
// properties to change the shadow color & offset
#property (nonatomic, retain) UIColor *textShadowColor;
#property (nonatomic) CGSize textShadowOffset;
- (id)initWithFrame:(CGRect)frame
font:(UIFont *)font
textColor:(UIColor *)textColor
shadowColor:(UIColor *)shadowColor
shadowOffset:(CGSize)shadowOffset;
#end
ShadowTextField .m file
#import "ShadowTextField.h"
#interface ShadowTextField ()
#property (nonatomic, retain) UILabel *internalLabel;
#end
#implementation ShadowTextField
#synthesize internalLabel = _internalLabel;
#synthesize textShadowColor = _textShadowColor;
#synthesize textShadowOffset = _textShadowOffset;
- (id)initWithFrame:(CGRect)frame
font:(UIFont *)font
textColor:(UIColor *)textColor
shadowColor:(UIColor *)shadowColor
shadowOffset:(CGSize)shadowOffset
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
// register to my own text changes notification, so I can update the internal label
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleUITextFieldTextDidChangeNotification)
name:UITextFieldTextDidChangeNotification
object:nil];
self.font = font;
self.textColor = textColor;
self.textShadowColor = shadowColor;
self.textShadowOffset = shadowOffset;
}
return self;
}
// when the user enter text we update the internal label
- (void)handleUITextFieldTextDidChangeNotification
{
self.internalLabel.text = self.text;
[self.internalLabel sizeToFit];
}
// init the internal label when first needed
- (UILabel *)internalLabel
{
if (!_internalLabel) {
_internalLabel = [[UILabel alloc] initWithFrame:self.bounds];
[self addSubview:_internalLabel];
_internalLabel.font = self.font;
_internalLabel.backgroundColor = [UIColor clearColor];
}
return _internalLabel;
}
// override this method to update the internal label color
// and to set the original label to clear so we wont get two labels
- (void)setTextColor:(UIColor *)textColor
{
[super setTextColor:[UIColor clearColor]];
self.internalLabel.textColor = textColor;
}
// override this method to update the internal label text
- (void)setText:(NSString *)text
{
[super setText:text];
self.internalLabel.text = self.text;
[self.internalLabel sizeToFit];
}
- (void)setTextShadowColor:(UIColor *)textShadowColor
{
self.internalLabel.shadowColor = textShadowColor;
}
- (void)setTextShadowOffset:(CGSize)textShadowOffset
{
self.internalLabel.shadowOffset = textShadowOffset;
}
- (void)drawTextInRect:(CGRect)rect {
// don't draw anything
// we have the internal label for that...
}
- (void)dealloc {
[_internalLabel release];
[_textShadowColor release];
[super dealloc];
}
#end
Here is how you use it in your view controller
- (void)viewDidLoad
{
[super viewDidLoad];
ShadowTextField *textField = [[ShadowTextField alloc] initWithFrame:CGRectMake(0, 0, 320, 30)
font:[UIFont systemFontOfSize:22.0]
textColor:[UIColor whiteColor]
shadowColor:[UIColor redColor]
shadowOffset:CGSizeMake(0, 1) ] ;
textField.text = #"This is some text";
textField.backgroundColor = [UIColor blackColor];
[self.view addSubview:textField];
}
You could try to do the drawing of the label yourself. Remove
[super drawTextInRect:rect]
And instead draw your own label. I haven't tried this but it could look something like this:
// Declare a label as a member in your class in the .h file and a property for it:
UILabel *textFieldLabel;
#property (nonatomic, retain) UILabel *textFieldLabel;
// Draw the label
- (void)drawTextInRect:(CGRect)rect {
if (self.textFieldLabel == nil) {
self.textFieldLabel = [[[UILabel alloc] initWithFrame:rect] autorelease];
[self.view addSubview:myLabel];
}
self.textFieldLabel.frame = rect;
self.textFieldLabel.text = self.text;
/** Set the style you wish for your label here **/
self.textFieldLabel.shadowColor = [UIColor grayColor];
self.textFieldLabel.shadowOffset = CGSizeMake(2,2);
self.textFieldLabel.textColor = [UIColor blueColor];
// Do not call [super drawTextInRect:myLabel] method if drawing your own text
}
Stop calling super and render the text yourself.
Have your tried with the standard shadow properties of the CALayer? it usually is enough and it is lot simpler. Try something like this with a regular UITextField:
self.inputContainer.layer.shadowColor=[UIColor blackColor].CGColor;
self.inputContainer.layer.shadowRadius=8.0f;
self.inputContainer.layer.cornerRadius=8.0f;
self.inputContainer.layer.shadowOffset=CGSizeMake(0, 4);
You need to import QuartzCore first of course!
#import <QuartzCore/QuartzCore.h>
I'm working on creating a rotation of 32 names using UILabels. How would I random rotate all 32 names?
- (IBAction)buttonPressed
{
int randomInt = rand() % [nameArray count];
[nameLabel setText:[nameArray objectAtIndex:randomInt]]
}
In your .h file you must have:
IBOutlet UILabel *nameLabel;
EDIT
I built this project and here is the exact code I used:
This is the .h file:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
IBOutlet UILabel *nameLabel;
NSArray *nameArray;
}
- (IBAction)buttonPressed;
#end
This is the .m file:
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
nameArray = [[NSArray alloc] initWithObjects:#"name1", #"name2", #"name3", #"name4", #"name5", #"name6", nil];
}
- (IBAction)buttonPressed
{
int randomInt = rand() % [nameArray count];
[nameLabel setText:[nameArray objectAtIndex:randomInt]];
}
- (void)dealloc
{
[super dealloc];
[nameArray release];
nameArray = nil;
}
#end
Make sure that both the UILabel and button actions are connected in interface builder.
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
NSMutableArray *nameArray;
NSMutableArray *textFieldArray;
UIScrollView *scrollView;
}
- (IBAction)buttonPressed;
- (void)addTextFields:(int)count;
// Random sort function for the shuffle method
int randomSort(id obj1, id obj2, void *context );
#end
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// If you want to pre load values
nameArray = [[NSMutableArray alloc] initWithObjects:#"name1", #"name2", #"name3", #"name4", #"name5", #"name6", nil];
// Initilize the array to contain all the textfields
textFieldArray = [[NSMutableArray alloc] init];
// inititlize and add the scrollview
scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
[self.view addSubview:scrollView];
// Create and add the button to randomize the fields
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setFrame:CGRectMake(self.view.frame.size.width/2 - 150, 20, 150, 50)];
[button addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"Randomize" forState:UIControlStateNormal];
[scrollView addSubview:button];
// method to create any number of textfields (currently sending number of items in nameArray)
[self addTextFields:[nameArray count]];
}
- (void)addTextFields:(int)count
{
// adjust these to get the size and positions you like
#define X_POSITION 20
#define TEXT_FIELD_WIDTH 300
#define TEXT_FIELD_HEIGHT 50
// Where to place the first text field
int yPosition = 90;
for (int textFieldCount = 0; textFieldCount<count; textFieldCount++) {
//Create and add the text field
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(X_POSITION, yPosition, TEXT_FIELD_WIDTH, TEXT_FIELD_HEIGHT)];
[textField setTag:textFieldCount];
[scrollView addSubview:textField];
[textFieldArray addObject:textField];
[textField setText:[nameArray objectAtIndex:textFieldCount]];
// Where to place the next text field
yPosition += (TEXT_FIELD_HEIGHT + 20);
}
// set the scroll view content size so it will fit all the text fields
[scrollView setContentSize:CGSizeMake(self.view.frame.size.width, yPosition+TEXT_FIELD_HEIGHT+20)];
}
- (IBAction)buttonPressed
{
// release and remove everyting from the name array
[nameArray release];
nameArray = nil;
// reinitilize the name array
nameArray = [[NSMutableArray alloc] init];
// Loop through the textfields to get the names into the nameArray
for (int textFieldCount = 0; textFieldCount<[textFieldArray count]; textFieldCount++) {
[nameArray addObject:[[textFieldArray objectAtIndex:textFieldCount] text]];
}
// Randomly sort the names in the array
[nameArray sortUsingFunction:randomSort context:nil];
// Add the random names back into the text fields
for (int textFieldCount = 0; textFieldCount<[textFieldArray count]; textFieldCount++) {
[[textFieldArray objectAtIndex:textFieldCount] setText:[nameArray objectAtIndex:textFieldCount]];
}
}
int randomSort(id obj1, id obj2, void *context ) {
// returns random number -1 0 1
return (arc4random()%3 - 1);
}
- (void)dealloc
{
[super dealloc];
[nameArray release];
nameArray = nil;
}