I am new to iOS app development. currently I am working on a very simple application that displays two words on the screen and the user selects one and the app just outputs you have selected x.
I have created two plists and i have loaded them onto an array and randomised them in the array. On my view I have two buttons that i want the words to display on them. However, I am having two problems..
1 . I want the label on the buttons to change when the app starts. So the user doesn't have to tap on the button or anything.
2. I want one random word from array_1 (loaded from a plist) to appear on a random button. either button_1 or button_2 and the same for list array_2.
Here is what i have done so far. (with some help from forums (: )
- (IBAction)buttonpressed:(id)sender {
// Load contents of plist onto array
NSString *path = [[NSBundle mainBundle] pathForResource:#"wordsOne" ofType:#"plist"];
NSMutableArray *words = [NSMutableArray arrayWithContentsOfFile:path];
//shuffle them using Fisher–Yates shuffle algorithm
for (int i = words.count-1; i>=0; i--) {
int r = arc4random_uniform(words.count);
[words exchangeObjectAtIndex:i withObjectAtIndex:r];
}
// assign word to the button
for (int j =0; j<_WordButton.count; j++) {
UIButton *button = [_WordButton objectAtIndex:j];
button.titleLabel.text = [words objectAtIndex:j];
}
}
There are obviously flaws in the above code, for example it uses only one plist and it doesn't display words on both buttons randomly.
You can set UIButton Title by using following code:
[button setTitle:titleString forState:UIControlStateNormal];
To achieve what you are looking to do you have to create an IBOutlet to the buttons on your .xib file. You can do this by using an easy Xcode shortcut that will create the IBOutlet code and make the connection from the .xib file to the code simultaneously for you:
Open up the .xib file in Xcode which will show a graphic file using Interface Builder.
In the toolbar at the top-right of Xcode is an icon that allows you to toggle through different modes, select the 'Assistant Editor'. The Interface Builder will slide over to share the window with a code file, this should automatically select your ViewController.h
The toolbar should look like this:
Insert some curly-brace in your code like so:
`
#interface CustomViewController : UIViewController {
// This is where you will control-drag to from the Interface Builder to have it create an IBOutlet to the button for you
}
// Your already set-up IBAction Method
- (IBAction)buttonpressed:(id)sender
#end
`
Control-drag from the button you wish your label to change to the area between the curly-braces in the .h file:
A new dialog box will appear. Make sure that the settings are as follow:
a. Connection = IBOutlet
b. Name = (Whatever you want to call the button, you've used '_wordButton')
c. Type = UIButton
d. Storage = WEAK
Now in your action method - (IBAction)buttonpressed:(id)sender and in your application:didFinishLaunchingWithOptions (to automatically load a word into the label when the application is launched) you can set the button title with the following:
`
// Create a string from the word that you pull out of the plist file
NSString *labelWord = ???;
// Set the label of the button
[_wordLabel setTitle:word forState:UIControlStateNormal];
`
Do it like this:
-(void)viewDidLoad{
[self setnewtitle];
}
-(void)setnewtitle{
NSString *pathone = [[NSBundle mainBundle] pathForResource:#"wordsOne" ofType:#"plist"];
NSMutableArray *wordsOne = [NSMutableArray arrayWithContentsOfFile:pathone];
NSString *pathtwo = [[NSBundle mainBundle] pathForResource:#"wordsOne" ofType:#"plist"];
NSMutableArray *wordsTwo = [NSMutableArray arrayWithContentsOfFile:pathtwo];
int words = "the number of objects(words) in your plist";
int randombutton = arc4random() % 2;
int randomplist = arc4random() % 2;
int randomWord = arc4random() % words;
if (randombutton==0){
if (randomplist==0){
[[_WordButton objectatIndex:randombutton] setTitle:[wordsOne objectatIndex:randomWord]];
} else {
[[_WordButton objectatIndex:randombutton] setTitle:[wordsTwo objectatIndex:randomWord]];
}
}else {
if (randomplist==0){
[[_WordButton objectatIndex:randombutton] setTitle:[wordsOne objectatIndex:randomWord]];
} else {
[[_WordButton objectatIndex:randombutton] setTitle:[wordsTwo objectatIndex:randomWord]];
}
}
}
Please make sure that the in the Array contained Buttons are initialized and allocated, also
if you have any questions please be free to ask
Related
I have a UIViewController, and in that I have an array of questions that I pull from a sqlite3 query. I am then using a for loop to iterate through each question in the array to change the UILabel.text to display the question on the screen. This is actually working for the first question in the array!
I then have four buttons for answers. I want to make it so if one of the buttons is pressed, the answer is saved and the next question in the loop updates the UILabel.text.
The four answers never change as it is more of a survey than answers, so one of the answers is "I agree" or "disagree", so the button text never changes.
Is this possible?
I have been on here and Google to find a way to link the button pressed with completing each iteration of the loop without any luck.
Why are you iterating through questions and changing UILabel's text? Shouldn't be it changed only on tapping one of the survey buttons?
If I got you correctly, you should do following:
1) Declare three properties in your controller: NSArray *questions, NSMutabelArray *answers, NSInteger currentIndex;
2) Init/alloc them in viewDidLoad (except currentIndex, of course, set it to 0).
3) Fill up questions array with your question strings.
4) Set text to UILabel, label.text = questions[currentIndex];
5) create IBAction method and link it to all survey buttons.
6) in IBAction method, insert button's title to answers array and show next question.
- (void)viewDidLoad {
[super viewDidLoad];
self.questions = {your questions array};
self.answers = [[NSMutableArray alloc] init];
self.currentIndex = 0;
}
- (IBAction)btnClicked:(id)sender {
UIButton *btn = (UIButton *)sender;
NSString *title = btn.titleLabel.text;
[self.answers addObject:title];
currentIndex++;
label.text = questions[currentIndex];
}
I hope you will understand the code.
In short, yes this is possible.
You'll first want to keep track of the question that your user is currently on. You can do this by storing an index in an instance variable or, if you plan on allowing the user to open the app and start from where they left off, you can use NSUserDefaults, which writes to disk and will persist.
// In the interface of your .m file
int questionIndex;
// In viewDidLoad of your controller, however this will start for index 0, the beginning of your questions array
questionIndex = 0
By storing the index in NSUserDefaults, you can grab it in ViewDidLoad, and start from where the user last left off:
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:questionIndex] forKey:#"questionIndex"];
To store your answer, you could add a method for your buttons called answerTapped:,
- (void)answerTapped:(UIButton *)answerButton
{
// Grab the answer from the text within the label of the button
// NOTE: This assume your button text is the answer that you want saved
NSString *answer = answerButton.titleLabel.text;
// You can use your questionIndex, to store which question this answer was for and you can then take the answer and store it in sqlite or where you prefer...
}
You can add this method to your buttons like so
[answerButton addTarget:self action:#selector(answerTapped:) forControlEvents:UIControlEventTouchUpInside];
You could then write a method to increment questionIndex now that an answer button has been pressed.
- (void)incrementQuestionIndex
{
// Increment index
questionIndex += 1;
// Update and save value in UserDefaults
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:questionIndex] forKey:#"questionIndex"];
}
You could then call a separate, final method to update the question label.
- (void)updateQuestionLabel
{
// Grab the question using the index (omit this line and go straight to the next if storing the index in an iVar)
questionIndex = [[[NSUserDefaults standardUserDefaults] objectForKey:#"questionIndex"] integerValue];
// Grab the question using the index. Assumes you have a questions array storing your questions from sqlite.
NSString *question = [questions objectAtIndex:questionIndex];
// Update the question UILabel
[questionLabel setText:question];
}
I am using buttons and I assigned tag 0 to 10 . Then I made an action to get the clicked button's tag, and now I want to display the tag in a label . Also I have a cancel button C. If user wants to delete any number, he can click C button that I want to remove number from the label .
This is my screenshot to touch the number
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Ezywire";
addnum=[[NSMutableArray alloc]init];
numbber=[[NSString alloc]init];
}
- (IBAction)NumberAction:(id)sender {
NSInteger tagvalue = [sender tag];
NSString *current=[NSString stringWithFormat:#"%ld", (long)tagvalue];
[addnum addObject:current];
NSString *temp;
for ( int i=0; i<[addnum count]; i++) {
numbber=[numbber stringByAppendingString:[addnum objectAtIndex:i]];
}
NSLog(#"data===%#",numbber);
ValueLable.text= numbber;
}
But in the label I am getting repeated number like this. How to implement this.
For example if user enters 2 then in the label
2
then he enters 7 then in the label
27
then he entered 9 then in the label
279
........ like this .
If user clicks C, then it remove from label last value is (last value removed)
27
The problem in your code is that numbber is initialized when the view is loaded, and never gets cleared again. However, each time a button is pressed, the whole addnum of digits gets appended to num again, creating repeated digits.
Fix this by removing num as an instance variable, making it a local to NumberAction: method, and setting it to an empty string every time the number is pressed.
Since you are planning to support the clearing action as well, you should make a private method that combines the digits from addnum array into a string. This way your NumberAction: and ClearAction would share the code that formats the array and sets the label. Your NumberAction: method would append a number and call FormatAndSetLabel, while the ClearAction method would remove the last digit if it is available, and call FormatAndSetLabel as well:
- (IBAction)NumberAction:(id)sender {
NSInteger tagvalue = [sender tag];
NSString *current=[NSString stringWithFormat:#"%ld", (long)tagvalue];
[addnum addObject:current];
[self FormatAndSetLabel];
}
- (IBAction)ClearAction:(id)sender {
if (!addnum.count) return;
[addnum removeLastObject];
[self FormatAndSetLabel];
}
-(void)FormatAndSetLabel {
NSMutableString *temp = [NSMutableString string];
for ( int i=0; i<[addnum count]; i++) {
[temp appendString:addnum[i]];
}
ValueLable.text= temp;
}
Also it might be interesting for you to have a look at Paul's Hegarty Stanford iOS development course (iPad and iPhone Application Development, Fall 2011)
https://itunes.apple.com/ru/itunes-u/ipad-iphone-application-development/id473757255?mt=10
Calculator app is used here as an example. Must see for the beginners.
I am trying to populate a UILabel with strings randomly chosen from an array. For some reason, the random choosing from array doesn't occur (the label always displays the first element of the array).
//.h file has declaration as follows
NSMutableArray *array;
//.m file
- (void)viewDidLoad
{
array = [[NSMutableArray alloc] initWithObjects: #"abc", #"def", nil];
}
and then, I have a method called orientationPopulate that does this:
-(void)labelPopulate;
{
int randomArrayIndex = arc4random() % array.count;
//Setting the label's text
_label.text = array[randomArrayIndex];
}
Based on the label displayed randomly, I would click buttons on the screen. So the label must keep changing each time. I do not know if I'm missing some link here. Can somebody help?
randomArrayIndex is 0 or 1, it may not change every time you click the button
I have recently released my first app to the App Store and still have a very long way to go with iOS development.
I'm looking to introduce themes into my app as an update so the user can select from 4-5 different themes.
I've got a tab bar controller and have set the 5th tab to be the "Settings" tab which contains a Table View with cells. The first cell contains the text "Themes" where the user can select it, be taken to a new Table view/Collection View to select the themes.
So I searched online and came across this incredible answer on doing just this:
How to create Multiple Themes/Skins for iphone apps?
Because I'm still new to development, I'm in need of assistance to take this forward.
To start off with, I have two themes:
1) DefaultTheme (Newiphonebackground.png)
2) PurplePinkTheme (Purplepinknew.png)
Following the instructions, I have created one plist for the Default theme and one plist for the PurplePink theme.
In the ThemeManager class that I created, I have:
- (id)init
{
if ((self = [super init]))
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *themeName = [defaults objectForKey:#"theme"] ?: #"DefaultTheme";
NSString *path = [[NSBundle mainBundle] pathForResource:themeName ofType:#"plist"];
self.styles = [NSDictionary dictionaryWithContentsOfFile:path];
}
return self;
}
+ (ThemeManager *)sharedManager
{
static ThemeManager *sharedManager = nil;
if (sharedManager == nil)
{
sharedManager = [[ThemeManager alloc] init];
}
return sharedManager;
}
In my table view, where the theme will get applied (it's going to get applied to every screen in the app but this is just to start off with where I'm testing with one scene in the app), in the viewDidLoad, I put:
NSDictionary *styles = [ThemeManager sharedManager].styles;
NSString *imageName = [styles objectForKey:#"DefaultTheme"];
UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
self.tableView.backgroundView = backgroundImageView;
That does nothing different because it applies the default theme. However if in the ThemeManager, I change the plist to be:
NSString *themeName = [defaults objectForKey:#"theme"] ?: #"PurplePinkTheme";
and in the viewDidLoad of the separate Table View, I set the code to be:
NSString *imageName = [styles objectForKey:#"PurplePinkTheme"];
Then upon loading my application, my PurplePinkTheme loads.
So far so good, but I don't think I've done anything substantial here.
I am confused from this point on. I am looking to start off with changing just the background images from the in-app settings and once I have that done, I'll look to change the custom navigation bars, etc.
So my questions are:
1) Why do I create one plist per theme?
2) How exactly do I link multiple plists in the ThemeManager class?
3) How do I link all of the themes up to the settings Theme cells allowing the user to choose?
I'm sorry this is vague, but I really need to understand how exactly I can carry on here. For example, I just don't get how to have multiple plists in the ThemeManager and how to move forward from here.
To recap, I, for now just want the ability to have multiple plist files with the different backgrounds, and for the user to go the settings tab in my app, click on the "Themes" cell and be able to select a different theme for the app without restarting the app.
I know the tutorial does carry on with explanations on that, but I'm just not quite sure I understand it all.
Any guidance on this would be massively appreciated.
Many thanks,
Your question is super long so I must confess I did not read the whole thing. That said I spent a lot of time with themes and the best solution I have found is to create an object that handles formatting. This is how I think you can implement it:
Create a formatter object extending NSObject
Have a property for each changeable piece of the theme:
for example if the background changes images you can have a UIImage in there called background. If the font color changes you have a UIFont property in there.
create a shared instance of your formater by adding:
+(Formater *) sharedInstance; //add to .h
+ (Formater *) sharedInstance //add to .m
{
if (!_sharedInstance)
{
_sharedInstance = [[Formater alloc] init];
}
}
Now in your view controller all you need to do is create a reference to your shared item and use that to style your view controller. (remember to make the changes in viewWillAppear not or it will not change after the setting is changed.
Voila!
I have a button named by
UIButton *button1;
how can i save 'button1' in string? or am i able to save it or not?
You can save its' address in memory only: NSString *but1=[NSString stringWithFormat:#"%#",&button1];, but if you need to get unique indicator of your buttons, you can use its' tags: button1.tag
Or you can create NSMutableDictionary and add buttons for keys, which equals their names.
You can create a macro like this:
#define getVariableName(var) [NSString stringWithFormat:#"%s", #var]
And use it:
NSLOG(#"My variable name is %#", variableName(self.button1));
You'll see
My variable name is button1
No you can't do this, as UIButton is an object and you are declaring UIButton as button1. This will remain static as it holds the reference in memory.
NSString is something that you can chage any time, but for Object and varible declaration you can't change it.
you get button title in string but not saved button outlet in string you save button outlet in id using this you save button title
NSString *btn = Mybutton.titleLabel.text;
for save button outlet
Iboutlet Uibutton *myButton;
id *myBtn=myButton;
Check this
import
#import "objc/runtime.h"
-(IBAction)btnItemListClicked:(id)sender
{
UIButton *btn=sender;
NSString *name = nil;
uint32_t ivarCount;
Ivar *ivars = class_copyIvarList([self class], &ivarCount);
if(ivars)
{
for(uint32_t i=0; i<ivarCount; i++)
{
Ivar ivar = ivars[i];
id pointer = object_getIvar(self, ivar);
if(pointer == sender)
{
name = [NSString stringWithUTF8String:ivar_getName(ivar)];
break;
}
}
free(ivars);
}
NSLog(#"%#", name);
}
Output is:
Printing description of name:
btnconferenceCall
Check this sample demo
ButtonDemo