I want to make a synchronized show lyric app and all lyric shown on a UITextView. In order to highlight current lyric I add background color to NSAttributedString of UITextView. All NSRange of lines stored in a NSArray.
My code is pretty simple, when button tapped move the highlight line down (via set contentOffset of UITextView). But here a strange problem occurred. In the beginning, the UITextView scroll properly but when contentOffset of UITextView greater then its frame.size.height it was fixed.
Here is my code:
//View controller
#import "ViewController.h"
#interface ViewController () {
NSUInteger globelIndex;
NSArray *textRanges;
NSMutableAttributedString *attributedText;
}
#property (weak, nonatomic) IBOutlet UITextView *lyricView;
#property (strong, nonatomic) NSTimer *mainTimer;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *rawText = [self readFile];
globelIndex = 0;
[self initTextLines:rawText];
attributedText = [[NSMutableAttributedString alloc] initWithString:rawText
attributes:#{NSBackgroundColorAttributeName: [UIColor orangeColor]}];
self.lyricView.attributedText = [attributedText copy];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)manualNextLine:(UIButton *)sender {
[self updateTextView];
}
- (IBAction)autoNextLineUsingNSTimer:(UIButton *)sender {
self.mainTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateTextView) userInfo:nil repeats:YES];
}
- (void)updateTextView {
if (self.lyricView.contentOffset.y >= self.lyricView.contentSize.height &&
self.mainTimer)
{
self.mainTimer = nil;
return;
}
NSMutableAttributedString *mat = [attributedText mutableCopy];
NSValue *value = [textRanges objectAtIndex:globelIndex];
[mat addAttribute:NSBackgroundColorAttributeName value:[UIColor whiteColor] range:[value rangeValue]];
self.lyricView.attributedText = [mat copy];
globelIndex += 1;
// self.textView.contentOffset = CGPointMake(self.textView.contentOffset.x, self.textView.contentOffset.y + 24);
// [self.textView scrollRangeToVisible:[value rangeValue]];
CGPoint newOffset = CGPointMake(self.lyricView.contentOffset.x, self.lyricView.contentOffset.y + 20);
[self.lyricView setContentOffset:newOffset animated:NO];
NSLog(#"[%# %#] h: %f b: %f a: %f", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.lyricView.contentSize.height, newOffset.y, self.lyricView.contentOffset.y);
}
#pragma mark - helper
- (void)initTextLines:(NSString *)rawText {
NSMutableArray *result = [#[] mutableCopy];
NSArray *t = [rawText componentsSeparatedByString:#"\r\n"];
__block int index = 0;
[t enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSString *s = obj;
NSRange range = NSMakeRange(index, s.length + 2);
[result addObject:[NSValue valueWithRange:range]];
index += s.length + 2;
}];
textRanges = [result copy];
}
- (NSString *)readFile {
NSError *error = nil;
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:#"二人の季節が-ささきのぞみ-想い" withExtension:#"lrc"];
NSString *content = [NSString stringWithContentsOfURL:fileURL encoding:NSUTF8StringEncoding error:&error];
if (error) {
if (DEBUG) NSLog(#"[%# %#] Error: %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error.localizedDescription);
abort();
}
return content;
}
#end
All my code was in ViewController and StoryBoard has two UIButton and a UITextView.
What I wonder is "Why the UITextView.contentOffset cannot change when it greater than some size".
Maybe rewrite setContentOffset:animated is helpful for you!
Here is some sample code which you can borrow:
https://github.com/360/Three20/blob/master/src/Three20UI/Sources/TTTextView.m
#import "Three20UI/TTTextView.h"
// UI
#import "Three20UI/UIViewAdditions.h"
#implementation TTTextView
#synthesize autoresizesToText = _autoresizesToText;
#synthesize overflowed = _overflowed;
- (void)setContentOffset:(CGPoint)offset animated:(BOOL)animated {
if (_autoresizesToText) {
if (!_overflowed) {
// In autosizing mode, we don't ever allow the text view to scroll past zero
// unless it has past its maximum number of lines
[super setContentOffset:CGPointZero animated:animated];
} else {
// If there is an overflow, we force the text view to keep the cursor at the bottom of the
// view.
[super setContentOffset: CGPointMake(offset.x, self.contentSize.height - self.height)
animated: animated];
}
} else {
[super setContentOffset:offset animated:animated];
}
}
#end
Related
Hi everyone iam new in objective c, now i try to create the app like "What's the word". I find this tutorial and lerned it as well as i can. But i have some problems. I want when i click on buttons the currentTitle replace the lable in placesView. Button click method in LettersView.m named as "displayChar". I have success in getting currentTitle but now i don't know how to pass it to GameController and paste text on "places".
I will be grateful for any help!
Here is my code
LettersView.h
#import <UIKit/UIKit.h>
#class LettersView;
#protocol LetterClickDelegateProtocol <NSObject>
-(void)letterView:(LettersView*)letterView addChar:(NSString *)addChar;
#end
#interface LettersView : UIImageView
#property (strong, nonatomic, readonly) NSString* letter;
#property (assign, nonatomic) BOOL isMatched;
#property (strong, nonatomic) NSString *clickLetter;
#property (weak, nonatomic) id<LetterClickDelegateProtocol> clickDelegate;
#property (strong, nonatomic) UIButton *lblChar;
-(instancetype)initWithLetter:(NSString*)letter andSideLength:(float)sideLength;
#end
LettersView.m
#import "LettersView.h"
#import "config.h"
#implementation LettersView{
NSInteger _xOffset, _yOffset;
}
- (id)initWithFrame:(CGRect)frame
{
NSAssert(NO, #"Use initWithLetter:andSideLength instead");
return nil;
}
-(instancetype)initWithLetter:(NSString*)letter andSideLength:(float)sideLength
{
//the letter background
UIImage* img = [UIImage imageNamed:#"btn_letter#2x.png"];
//create a new object
self = [super initWithImage:img];
if (self != nil) {
//resize the letters
float scale = sideLength/img.size.width;
self.frame = CGRectMake(0,0,img.size.width*scale, img.size.height*scale);
UIButton *lblChar = [[UIButton alloc] initWithFrame:self.bounds];
lblChar.tintColor = [UIColor blackColor];
lblChar.backgroundColor = [UIColor clearColor];
[lblChar setTitle:letter forState:UIControlStateNormal];
[lblChar addTarget:self action:#selector(displaychar:)forControlEvents:UIControlEventTouchUpInside];
[self addSubview:lblChar];
self.isMatched = NO;
_letter = letter;
self.userInteractionEnabled = YES;
}
return self;
}
-(void)displayChar:(id)sender {
UIButton *lblChar = (UIButton *)sender;
NSLog(#" The button's title is %#.", lblChar.currentTitle);
_clickLetter = lblChar.currentTitle;
if (self.clickDelegate) {
[self.clickDelegate letterView:self addChar:lblChar.currentTitle];
}
NSLog(#"hu %#", _clickLetter);
}
PlacesView.h
// PlacesView.m
#import "PlacesView.h"
#import "config.h"
#implementation PlacesView
-(id)initWithFrame:(CGRect)frame {
NSAssert(NO, #"Use initwithletter");
return nil;
}
-(instancetype)initWithLetter:(NSString *)letter andSideLength:(float)sideLength
{
UIImage *img = [UIImage imageNamed:#"btn_input#2x.png"];
self = [super initWithImage: img];
if (self != nil) {
self.isMatched = NO;
float scale = sideLength/img.size.width;
self.frame = CGRectMake(0, 0, img.size.width*scale, img.size.height*scale);
//bullshit time
_fieldForLetter = [[UILabel alloc] initWithFrame:self.bounds];
_fieldForLetter.textAlignment = NSTextAlignmentCenter;
_fieldForLetter.textColor = [UIColor blackColor];
_fieldForLetter.backgroundColor = [UIColor clearColor];
_fieldForLetter.text = #"*"; // if button pressed button title placed here.
[self addSubview:_fieldForLetter];
_letter = letter;
}
return self;
}
#end
GameController.m
#import "GameController.h"
#import "config.h"
#import "LettersView.h"
#import "PlacesView.h"
#import "AppDelegate.h"
#implementation GameController {
//tile lists
NSMutableArray* _letters;
NSMutableArray* _places;
}
-(instancetype)init {
self = [super init];
if (self != nil) {
self.points = [[PointsController alloc] init];
self.audioController = [[AudioController alloc] init];
[self.audioController preloadAudioEffects: kAudioEffectFiles];
}
return self;
}
-(void)dealRandomWord {
NSAssert(self.level.words, #"Level not loaded");
// random word from plist
NSInteger randomIndex = arc4random()%[self.level.words count];
NSArray* anaPair = self.level.words[ randomIndex ];
NSString* word1 = anaPair[1]; // answer
NSString* word2 = anaPair[2]; // some letters
_helpstr = anaPair[3]; // helper
NSLog(#"qweqweq %# %#" , word1 , word2);
NSInteger word1len = [word1 length];
NSInteger word2len = [word2 length];
NSLog(#"phrase1[%li]: %#", (long)word1len, word1);
NSLog(#"phrase2[%li]: %#", (long)word2len, word2);
//calculate the letter size
float letterSide = ceilf( kScreenWidth*0.9 / (float)MAX(word1len, word2len) ) - kTileMargin;
//get the left margin for first letter
float xOffset = (kScreenWidth - MAX(word1len, word2len) * (letterSide + kTileMargin))/2;
//adjust for letter center
xOffset += letterSide/2;
float yOffset = 1.5* letterSide;
// init places list
_places = [NSMutableArray arrayWithCapacity: word1len];
// create places
for (NSInteger i = 0; i<word1len; i++){
NSString *letter = [word1 substringWithRange:NSMakeRange(i, 1)];
if (![letter isEqualToString:#" "]) {
PlacesView* place = [[PlacesView alloc] initWithLetter:letter andSideLength:letterSide];
place.center = CGPointMake(xOffset + i*(letterSide + kTileMargin), kScreenHeight/4);
[self.gameView addSubview:place];
[_places addObject: place];
}
}
//init letters list
_letters = [NSMutableArray arrayWithCapacity: word2len];
//create letter
for (NSInteger i=0;i<word2len;i++) {
NSString* letter = [word2 substringWithRange:NSMakeRange(i, 1)];
if (![letter isEqualToString:#" "]) {
LettersView* letv = [[LettersView alloc] initWithLetter:letter andSideLength:letterSide];
letv.center = CGPointMake(xOffset + i * (letterSide + kTileMargin), kScreenHeight); // "/3*4"
if (i > 6) {
letv.center = CGPointMake(-5.15 * xOffset + i * (letterSide + kTileMargin), kScreenHeight + yOffset); // "/3*4"
}
letv.clickDelegate = self;
[self.gameView addSubview:letv];
[_letters addObject: letter];
}
}
}
-(void)letterView:(LettersView *)letterView addChar:(NSString *)addChar
{
PlacesView* placesView = nil;
for (PlacesView* pl in _places) {
//if (CGRectContainsPoint(pl.frame, pt)) {
if () {
//placesView = pl;
placesView.fieldForLetter.text = letterView.lblChar.currentTitle;
break;
}
}
//1 check if target was found
if (placesView!=nil) {
//2 check if letter matches
if ([placesView.letter isEqualToString: letterView.letter]) {
[self placeLetter:letterView atTarget:placesView];
[self.audioController playEffect: kSoundLetterTap];
self.points.points += self.level.coinsPerLvl; //ne nado tak
NSLog(#"Current points %d" , self.points.points);
[self checkForSuccess];
} else {
[self.audioController playEffect:kSoundFail];
[self addAlert:#"ne success" andMessage:#"You lose!" andButton:#"eshe cyka"];
}
}
}
-(void)placeLetter:(LettersView*)letterView atTarget:(PlacesView*)placeView {
placeView.isMatched = YES;
letterView.isMatched = YES;
letterView.userInteractionEnabled = NO;
}
-(void)checkForSuccess {
for (PlacesView* p in _places) {
//no success, bail out
if (p.isMatched==NO) return;
}
NSLog(#"ya!");
[self addAlert:#"Success" andMessage:#"You win!" andButton:#"eshe cyka"];
[self.audioController playEffect:kSoundSuccess];
}
-(void)addAlert: (NSString *)addTitle andMessage: (NSString *)alertMessage andButton: (NSString *)alertButton {
dispatch_async(dispatch_get_main_queue(), ^{
UIWindow* window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
window.rootViewController = [UIViewController new];
window.windowLevel = UIWindowLevelAlert + 1;
UIAlertController *alert = [UIAlertController alertControllerWithTitle: addTitle message:alertMessage preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *defaultAction= [UIAlertAction actionWithTitle:alertButton style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
window.hidden = YES;
}];
[alert addAction:defaultAction];
[window makeKeyAndVisible];
[window.rootViewController presentViewController:alert animated:YES completion:nil];
});
}
#end
Your GameController needs to keep a reference to PlacesView. It can also assign the action into LettersView so when the button in LettersView is pressed, the GameController will fetch it and perform an action in PlacesView. GameController is what both the other classes have in common, so it can handle any actions between them.
Another option is to use NSNotificationCenter and post a message in LettersView when the button is pressed, and listen for it in PlacesView.
Yet anther way is using a delegates where GameController makes sure that PlacesView is set as the delegate. When LettersView's button is pressed, it will call the delegate method which PlacesView listens to.
I'd go with first option.
I know this was already asked on here and I have used code from it but I still can't pass value of double grandTotal (from InitialStoreViewController) to double isSomethingEnabled (in ViewController). Here are my view controller files:
InitialStoreViewController.h
#import <UIKit/UIKit.h>
#import "InitialStoreViewController.h"
#import "ViewController.h"
#interface InitialStoreViewController : UITableViewController<UITextFieldDelegate>
{
// TargetViewCon TargetViewController *targetView;
IBOutlet UILabel *peasLabel;
IBOutlet UILabel *eggsLabel;
IBOutlet UILabel *milkLabel;
IBOutlet UILabel *beansLabel;
// requested amounts of each product
int peasAmountInt;
int eggsAmountInt;
int milkAmountInt;
int beansAmountInt;
double peasTotal;
double eggsTotal;
double milkTotal;
double beansTotal;
double grandTotal;
}
- (IBAction)peasStepper:(UIStepper *)sender;
- (IBAction)eggsStepper:(UIStepper *)sender;
- (IBAction)milkStepper:(UIStepper *)sender;
- (IBAction)beansStepper:(UIStepper *)sender;
- (IBAction)calcTotal:(UIBarButtonItem *)sender;
#property double price;
#property double priceToPass;
//this method is
//- (void) stepperAction: (UIStepper*)stepper toLabel: (UILabel*)label;
#end
InitialStoreViewController.m
#import "InitialStoreViewController.h"
#import "ViewController.h"
#import "Product.h"
#implementation InitialStoreViewController
- (void)viewDidLoad
{
//sunday:
[super viewDidLoad];
}
- (IBAction)peasStepper:(UIStepper *)sender
{
peasAmountInt = (int) sender.value;
NSLog(#"Peas Amount: %i", peasAmountInt);
peasLabel.text = [NSString stringWithFormat:#"%i", peasAmountInt];
//Initiating object of class Product
Product *peas = [[Product alloc]init];
peas.amountInt = peasAmountInt;
peasTotal = [peas multiplyAmount: peas.amountInt byPrice:0.95];
NSLog(#"Total amount for peas: %f", peasTotal);
grandTotal = peasTotal + eggsTotal + milkTotal + beansTotal;
NSLog(#"TOTAL Amount: %f", grandTotal);
}
- (IBAction)eggsStepper:(UIStepper *)sender
{
eggsAmountInt = (int) sender.value;
NSLog(#"Eggs Amount: %i", eggsAmountInt);
eggsLabel.text = [NSString stringWithFormat:#"%i", eggsAmountInt];
//Initiating object of class Product
Product *eggs = [[Product alloc]init];
eggs.amountInt = eggsAmountInt;
eggsTotal = [eggs multiplyAmount: eggs.amountInt byPrice:2.10];
NSLog(#"Total amount for eggs: %f", eggsTotal);
grandTotal = peasTotal + eggsTotal + milkTotal + beansTotal;
NSLog(#"TOTAL Amount: %f", grandTotal);
}
- (IBAction)milkStepper:(UIStepper *)sender
{
milkAmountInt = (int) sender.value;
NSLog(#"Milk Amount: %i", milkAmountInt);
milkLabel.text = [NSString stringWithFormat:#"%i", milkAmountInt];
//Initiating object of class Product
Product *milk = [[Product alloc]init];
milk.amountInt = milkAmountInt;
milkTotal = [milk multiplyAmount: milk.amountInt byPrice:1.30];
NSLog(#"Total amount for milk: %f", milkTotal);
grandTotal = peasTotal + eggsTotal + milkTotal + beansTotal;
NSLog(#"TOTAL Amount: %f", grandTotal);
}
- (IBAction)beansStepper:(UIStepper *)sender
{
beansAmountInt = (int) sender.value;
NSLog(#"Beans Amount: %i", beansAmountInt);
beansLabel.text = [NSString stringWithFormat:#"%i", beansAmountInt];
//Initiating object of class Product
Product *beans = [[Product alloc]init];
beans.amountInt = beansAmountInt;
beansTotal = [beans multiplyAmount: beans.amountInt byPrice:1.30];
NSLog(#"Total amount for beans: %f", beansTotal);
grandTotal = peasTotal + eggsTotal + milkTotal + beansTotal;
NSLog(#"TOTAL Amount: %f", grandTotal);
}
- (IBAction)calcTotal:(UIBarButtonItem *)sender
{
grandTotal = peasTotal + eggsTotal + milkTotal + beansTotal;
NSLog(#"TOTAL Amount: %f", grandTotal);
}
//sunday
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"showDetailSegue"]){
UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
ViewController *controller = (ViewController *)navController.topViewController;
// controller.isSomethingEnabled = YES;
controller.isSomethingEnabled = &(grandTotal);
}
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#import "InitialStoreViewController.h"
#interface ViewController : UIViewController <UIPickerViewDataSource,
UIPickerViewDelegate>
{
NSArray *news;
NSMutableData *data;
double isSomethingEnabled;
}
#property(nonatomic) double *totalLabelDouble;
#property(nonatomic) double *isSomethingEnabled;
#property (nonatomic, strong) NSArray *currencyArray;
#property (weak, nonatomic) IBOutlet UILabel *totalLabel;
#property (weak, nonatomic) IBOutlet UIPickerView *picker;
#end
ViewController.m
#import "ViewController.h"
#import "Product.h"
#import "InitialStoreViewController.h"
#interface ViewController ()
#end
#implementation ViewController
//double totalLabelDouble = double isSomethingEnabled;
#synthesize currencyArray, totalLabel, picker;
- (void)viewDidLoad
{
[super viewDidLoad];
//checking if value of grandTotal was passed to this view controller:
NSLog(#"HHHHHHHHHHHHHHHHHHHHHHHHHHHH :%f", isSomethingEnabled);
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = [NSURL URLWithString:#"http://www.apilayer.net/api/live?access_key=0b8125d8ca8e2801643e360440409165"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
// Do any additional setup after loading the view, typically from a nib.
//connection:willCacheResponse
//connection:didReceiveResponse
//connection:didReceiveData
//connectionDidFinishLoading
//connection:didFailWithError
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
data = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData
{
[data appendData:theData];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
news= [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
//[mainTableView reloadData];
NSLog(#"RAW DATA Marcin %#", data);
//NEW Stuff:
// Now create a NSDictionary from the JSON data
// NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
// Create a new array to hold the locations
// NSMutableArray *locations = [[NSMutableArray alloc] init];
// Get an array of dictionaries with the key "locations"
// NSArray *array = [jsonDictionary objectForKey:#"USDGBP"];
// for (id USDGBP in array)
//NSLog(#"VALUEEEEEE %#", array);
// NSLog (#"%#", [[arrayController selectedObjects] valueForKey:#"USDGBP"]);
NSString *json_string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Data AS STRING %#", json_string);
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
double usdgbpValue = [jsonDict[#"quotes"][#"USDGBP"] doubleValue];
//NSArray *xxx = [jsonDict[#"quotes"][#"USDGBP"] array];
//NSLog(#"VALUEEEEEE %#", xxx);
NSDictionary *jsonDict2 = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
//double usdgbpValue2 = [jsonDict[#"quotes"][#"USDGBP"] doubleValue];
NSArray *CurrencyArray = [jsonDict2 objectForKey:#"quotes"];
NSLog(#"VALUE %#", CurrencyArray);
//below causing crash
//currencyArray = [[NSArray alloc]initWithArray:CurrencyArray];
//currencyArray = CurrencyArray;
//double usdgbpValue3 = [NSArray[#"USDGBP"]currencyArray];
NSLog(#"USDGBP :%f", usdgbpValue);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
//here to display message that internet connection is needed
}
//Creating product classes
//static Product *peas = nil;
//peas = [[Product alloc]init];
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UIPickerView Datasource & Delegate Methods
// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
// returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [currencyArray count];
}
- (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
__TVOS_PROHIBITED
{
return currencyArray[row];
}
/// NEW CODE
//NSLog(#"USDGBP :%f", isSomethingEnabled);
//UILabel totalLabel.text = [NSString stringWithFormat: #"%d",
//isSomethingEnabled];
#end
When I run the code I get value for grandTotal but below code shows 0.000 for isSomethingEnabled:
NSLog(#"HHHHHHHHHHHHHHHHHHHHHHHHHHHH :%f", isSomethingEnabled);
I have an Array with 10 Objects. I take the first Object and put it into my Label with a String.
Then I want to have a Method that increases the objectAtIndex by 1.
This is my Code :
//.m
#interface GameViewController () {
NSInteger _labelIndex;
}
#property (nonatomic) NSArray *playerArray;
#property (nonatomic) NSString *playerLabel;
- (void)viewDidLoad {
[super viewDidLoad];
self.playerArray = [NSArray arrayWithObjects:#"FIRST", #"SECOND", #"THIRD", #"FOURTH", #"FIFTH", #"SIXT", #"SEVENTH", #"EIGTH", #"NINTH", #"TENTH", nil];
_labelIndex = 0;
[self updateTurnLabel];
self.turnLabel.text = [NSString stringWithFormat:#"YOUR %# DRAW?", self.playerLabel];
}
Here I call the Method i another Method:
-(void) flipDraws {
self.boardView.userInteractionEnabled = NO;
[self updateTurnLabel];
CardView *cv1 = (CardView *) self.turnedDrawViews[0];
CardView *cv2 = (CardView *) self.turnedDrawViews[1];
}
This is my Method:
-(void) updateTurnLabel {
self.playerLabel = [self.playerArray objectAtIndex:_labelIndex % self.playerArray.count]; _labelIndex++;
}
I tried it with a for Loop but nothing happened. I tried it with just set the objectAtIndex:1 but my Method was not called.
What I am doing wrong?
{
int a;
}
- (void)viewDidLoad {
[super viewDidLoad];
a = 0;
self.playerArray = [NSArray arrayWithObjects:#"FIRST", #"SECOND", #"THIRD", #"FOURTH", #"FIFTH", #"SIXT", #"SEVENTH", #"EIGTH", #"NINTH", #"TENTH", nil];
self.playerLabel = [self.playerArray objectAtIndex:a];
self.turnLabel.text = [NSString stringWithFormat:#"YOUR %# DRAW?", self.playerLabel];
}
-(void) updateTurnLabel {
a +=1;
if (!a<[playerArray count])
{
a = 0;
}
self.playerLabel = [self.playerArray objectAtIndex:a];
}
call self.turnLabel.text = [NSString stringWithFormat:#"YOUR %# DRAW?", self.playerLabel]; after [self updateTurnLabel];
What are you adding +1 to in the method objectAtIndex:.
You should be maintaining a variable which tracks the current index being used, then in your method use this :
-(void) updateTurnLabel {
self.playerLabel = [self.playerArray objectAtIndex:currentIndex+1];
}
Hey I was wondering is their any possible way I can link two actions to the same button in Xcode? I've already tried but keep getting this error: "terminating with uncaught exception of type NSException". So i'm guessing I am not able to do that? See what i'm trying to do is
make a button play a sound but that same button is also linked to starting a new round in the game. How would I go about doing this? I've currently got this going in my .m file.
#import "BullsEyeViewController.h"
#interface BullsEyeViewController ()
#end
#implementation BullsEyeViewController
{
int _currentValue;
int _targetValue;
int _score;
int _round;
}
- (IBAction)playSound:(id)sender {
SystemSoundID soundID;
NSString *buttonName=[sender currentTitle];
NSString *soundFile=[[NSBundle mainBundle]
pathForResource:buttonName ofType:#"mp3"];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)
[NSURL fileURLWithPath:soundFile], &
soundID);
AudioServicesPlaySystemSound(soundID);
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self startNewGame];
[self updateLabels];
UIImage *thumbImageNormal = [UIImage
imageNamed:#"SliderThumb-Normal"];
[self.slider setThumbImage:thumbImageNormal
forState:UIControlStateNormal];
UIImage *thumbImageHighlighted = [UIImage
imageNamed:#"SliderThumb-Highlighted"];
[self.slider setThumbImage:thumbImageHighlighted
forState:UIControlStateHighlighted];
UIImage *trackLeftImage =
[[UIImage imageNamed:#"SliderTrackLeft"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 14, 0, 14)];
[self.slider setMinimumTrackImage:trackLeftImage
forState:UIControlStateNormal];
UIImage *trackRightImage =
[[UIImage imageNamed:#"SliderTrackRight"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 14, 0, 14)];
[self.slider setMaximumTrackImage:trackRightImage
forState:UIControlStateNormal];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)startNewRound
{
_round += 1;
_targetValue = 1 + arc4random_uniform(100);
_currentValue = 50;
self.slider.value = _currentValue;
}
- (void)startNewGame
{
_score = 0;
_round = 0;
[self startNewRound];
}
- (void)updateLabels
{
self.targetLabel.text = [NSString stringWithFormat:#"%d",
_targetValue];
self.scoreLabel.text = [NSString stringWithFormat:#"%d",
_score];
self.roundLabel.text = [NSString stringWithFormat:#"%d",
_round];
}
- (BOOL)prefersStatusBarHidden
{
return YES;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)showAlert
{
int difference = abs(_targetValue - _currentValue);
int points = 100 - difference;
NSString *title;
if (difference == 0) {
title = #"Perfect!";
points += 100;
} else if (difference < 5) {
title = #"You almost had it!";
if (difference == 1) {
points += 50;
}
} else if (difference < 10 ) {
title = #"Pretty good!";
} else {
title = #"Not even close...";
}
_score+=points;
NSString *message = [NSString stringWithFormat:#"You scored %d points", points];
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle: title
message:message
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[alertView show];
}
-(IBAction)sliderMoved:(UISlider *)slider
{
_currentValue = lroundf(slider.value);
}
- (void)alertView:(UIAlertView *)alertView
didDismissWithButtonIndex:(NSInteger)buttonIndex
{
[self startNewRound];
[self updateLabels];
}
-(IBAction)startOver
{
CATransition *transition = [CATransition animation];
transition.type = kCATransitionFade;
transition.duration = 1;
transition.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseOut];
[self startNewGame];
[self updateLabels];
[self.view.layer addAnimation:transition forKey:nil];
}
#end
And here's my .h file.
//
// BullsEyeViewController.h
// BullsEye
//
// Created by Sebastian Shelley on 28/04/2014.
// Copyright (c) 2014 Sebastian Shelley. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioToolbox.h>
#interface BullsEyeViewController : UIViewController
<UIAlertViewDelegate>
#property (nonatomic, weak) IBOutlet UISlider *slider;
#property (nonatomic, weak) IBOutlet UILabel *targetLabel;
#property (nonatomic, weak) IBOutlet UILabel *scoreLabel;
#property (nonatomic, weak) IBOutlet UILabel *roundLabel;
-(IBAction)showAlert;
-(IBAction)sliderMoved:(UISlider *)slider;
-(IBAction)startOver;
- (IBAction)playSound:(id)sender;
#end
Some help would be greatly appreciated :)
Add an action like this to the button
-(IBAction)myButtonPressed:(id)sender
{
[self playSound:sender];
[self startNewRound:Sender];
}
Use only one action, just set a BOOL to check if you need to play the sound or not.
Example code would be:
-(IBAiction)btnPressed:(id)sender
{
if(playsound)
{
[self playSound];
playsound = NO;
}
[self startOver];
}
And then whenever you want the saund to be played again just set playsound to YES and next time user presses the button it will play the sound again
i am developing very simple quiz app
In viewDidLoad i am adding objects in myarray
where ever i nslog myarray values it works fine
but if i try this inside ibaction methods all objects becomes zombie
for 2 days i am stuck in this but can't find it what is wrong.
quiz.h
#import <UIKit/UIKit.h>
#import <sqlite3.h>
#class dbVals;
#class viewTransition;
#class AppDelegate;
#interface quiz : UIViewController
{
NSMutableArray *myarray;
IBOutlet UITextView *questionTextView_;
IBOutlet UIButton *skipButton_;
IBOutlet UIButton *optionAButton_;
IBOutlet UIButton *optionBButton_;
IBOutlet UIButton *optionCButton_;
NSString *correctAnswer;
int questionNumber;
int score;
IBOutlet UILabel *scoreLabel_;
int totalQuestions;
}
-(void)populate:(int)number;
//#property(nonatomic, retain) NSMutableArray *myarray;
#property (retain, nonatomic) IBOutlet UITextView *questionTextView;
#property (retain, nonatomic) IBOutlet UIButton *skipButton;
#property (retain, nonatomic) IBOutlet UIButton *optionAButton;
#property (retain, nonatomic) IBOutlet UIButton *optionBButton;
#property (retain, nonatomic) IBOutlet UIButton *optionCButton;
#property (retain, nonatomic) IBOutlet UILabel *scoreLabel;
- (IBAction)optionsToAnswer:(id)sender;
- (IBAction)zzz:(id)sender;
#end
quiz.m
#import "quiz.h"
#import "DbVals.h"
#import "viewTransition.h"
#import "AppDelegate.h"
#implementation quiz
#synthesize skipButton=skipButton_;
#synthesize optionAButton=optionAButton_;
#synthesize optionBButton=optionBButton_;
#synthesize optionCButton=optionCButton_;
#synthesize scoreLabel=scoreLabel_;
#synthesize questionTextView=questionTextView_;
//#synthesize myarray;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)createEditableCopyOfDatabaseIfNeeded
{
//NSLog(#"Creating editable copy of database");
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"oq.sqlite"];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success) return;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"oq.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
+(sqlite3 *) getNewDBConnection
{
sqlite3 *newDBconnection;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"oq.sqlite"];
// Open the database. The database was prepared outside the application.
if (sqlite3_open([path UTF8String], &newDBconnection) == SQLITE_OK) {
//NSLog(#"Database Successfully Opened ");
} else {
NSLog(#"Error in opening database ");
}
return newDBconnection;
}
- (void)viewDidLoad
{
[super viewDidLoad];
questionNumber = 0;
score = 0;
[self createEditableCopyOfDatabaseIfNeeded];
sqlite3 *dbc = [quiz getNewDBConnection];
sqlite3_stmt *statement = nil;
const char *sqlSelect = "select * from QnA ORDER BY RANDOM()";
if(sqlite3_prepare_v2(dbc, sqlSelect, -1, &statement, NULL)!=SQLITE_OK)
{
NSAssert1(0, #"Error Preparing Statement", sqlite3_errmsg(dbc));
}
else
{
myarray = [[NSMutableArray alloc]init];
while(sqlite3_step(statement)==SQLITE_ROW)
{
NSString *q = [NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 0)];
NSString *o = [NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 1)];
NSString *a = [NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 2)];
DbVals *dbValsObj = [[DbVals alloc]init];
[dbValsObj setValsOfQuestions:q options:o answer:a];
[myarray addObject:dbValsObj];
[dbValsObj release];
}
}
sqlite3_finalize(statement);
//[self populate:questionNumber];
}
-(void)populate:(int)number
{
/*[scoreLabel_ setText:[NSString stringWithFormat:#"%d",score]];
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
[appDel setFinalScore:[NSString stringWithFormat:#"%d",score]];
if(number < [myarray count])
{
DbVals *dbv1 = [myarray objectAtIndex:number];
[questionTextView_ setText:[dbv1 getQuestions]];
NSString *joinedOptions = [dbv1 getOptions];
NSArray *splitOptions = [joinedOptions componentsSeparatedByString:#","];
[optionAButton_ setTitle:[splitOptions objectAtIndex:0] forState:UIControlStateNormal];
[optionBButton_ setTitle:[splitOptions objectAtIndex:1] forState:UIControlStateNormal];
[optionCButton_ setTitle:[splitOptions objectAtIndex:2] forState:UIControlStateNormal];
correctAnswer = [dbv1 getAnswer];
}
else
{
//viewTransition *vt = [[viewTransition alloc]init];
[viewTransition viewsTransitionCurrentView:self toNextView:#"result"];
//[vt release];
}*/
}
- (void)viewDidUnload
{
for(int i=0; i<[myarray count]; i++)
{
DbVals *dbv1 = [myarray objectAtIndex:i];
NSLog(#"%#",[dbv1 getQuestions]);
NSLog(#"%#",[dbv1 getOptions]);
NSLog(#"%#",[dbv1 getAnswer]);
NSLog(#"<u><u><u><u><><><><><><><><><><><>");
}
[self setQuestionTextView:nil];
[questionTextView_ release];
questionTextView_ = nil;
[self setQuestionTextView:nil];
[skipButton_ release];
skipButton_ = nil;
[self setSkipButton:nil];
[optionAButton_ release];
optionAButton_ = nil;
[self setOptionAButton:nil];
[optionBButton_ release];
optionBButton_ = nil;
[self setOptionBButton:nil];
[optionCButton_ release];
optionCButton_ = nil;
[self setOptionCButton:nil];
[scoreLabel_ release];
scoreLabel_ = nil;
[self setScoreLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc
{
for(int i=0; i<[myarray count]; i++)
{
DbVals *dbv1 = [myarray objectAtIndex:i];
NSLog(#"%#",[dbv1 getQuestions]);
NSLog(#"%#",[dbv1 getOptions]);
NSLog(#"%#",[dbv1 getAnswer]);
NSLog(#"<d><d><d><d><d><><><><><><><><><><>");
}
[questionTextView_ release];
[skipButton_ release];
[optionAButton_ release];
[optionBButton_ release];
[optionCButton_ release];
[scoreLabel_ release];
[myarray release];
[super dealloc];
}
- (IBAction)optionsToAnswer:(id)sender
{
for(int i=0; i<[myarray count]; i++)
{
DbVals *dbv1 = [myarray objectAtIndex:i];
NSLog(#"%#",[dbv1 getQuestions]);
NSLog(#"%#",[dbv1 getOptions]);
NSLog(#"%#",[dbv1 getAnswer]);
NSLog(#"six");
}
if(sender == skipButton_)
{
//questionNumber++;
//[self populate:questionNumber];
/*[UIView animateWithDuration:5 delay:0 options: UIViewAnimationCurveEaseOut
animations:
^{
[UIView setAnimationTransition:103 forView:self.view cache:NO];
}
completion:
^(BOOL finished)
{
}
];*/
}
if(sender == optionAButton_)
{
/*NSString *one = #"1";
if([correctAnswer isEqualToString:one])
{
score++;
}
questionNumber++;
[self populate:questionNumber];*/
}
if(sender == optionBButton_)
{
/*NSString *two = #"2";
if([correctAnswer isEqualToString:two])
{
score++;
}
questionNumber++;
[self populate:questionNumber];*/
}
if(sender == optionCButton_)
{
/*NSString *three = #"3";
if([correctAnswer isEqualToString:three])
{
score++;
}
questionNumber++;
[self populate:questionNumber];*/
}
}
- (IBAction)zzz:(id)sender
{
}
#end
dbVals.h
#import <Foundation/Foundation.h>
#interface DbVals : NSObject
{
NSString *questions_;
NSString *options_;
NSString *answer_;
// NSString *hint;
// NSString *mode;
}
-(void)setValsOfQuestions:(NSString*)questions options:(NSString*)options answer:(NSString*)answer;
-(NSString*)getQuestions;
-(NSString*)getOptions;
-(NSString*)getAnswer;
dbVals.m
#import "DbVals.h"
#implementation DbVals
-(void)setValsOfQuestions:(NSString*)questions options:(NSString*)options answer:(NSString*)answer
{
questions_ = questions;
options_ = options;
answer_ = answer;
}
-(NSString*)getQuestions
{
return questions_;
}
-(NSString*)getOptions
{
return options_;
}
-(NSString*)getAnswer
{
return answer_;
}
#end
Your dbVals.m setVals isn't retaining the parameters. This obviously means, everything inside becomes deallocated once the function scope ends.
Try changing it to something like
-(void)setValsOfQuestions:(NSString*)questions options:(NSString*)options answer:(NSString*)answer
{
[questions_ release];
[options_ release];
[answer_ release];
questions_ = [questions copy];
options_ = [options copy];
answer_ = [answer copy];
}