I am attempting to show a button in the selected state when based on a boolean off of JSON. Here is my code for my custom UITableViewCell:
TwitterCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"TwitterCell"];
if (cell == nil) {
cell = [[TwitterCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"TwitterCell"];
}
NSDictionary *data = tweets[indexPath.row];
id favorited = data[#"favorited"];
NSLog(#"%#",favorited);
id retweeted = data[#"retweeted"];
NSLog(#"%#",retweeted);
if ((int)favorited == 1) {
[cell.favoriteButton select];
} else {
[cell.favoriteButton deselect];
}
if ((int)retweeted == 1) {
[cell.retweetButton select];
} else {
[cell.retweetButton deselect];
}
Here is a possible point of issue in my custom TableViewCell class. Where I prepare for reuse:
- (void)prepareForReuse
{
[super prepareForReuse];
self.favoriteButton.selected = NO;
self.tweetLabel.text = nil;
self.profilePicture.image = nil;
self.nameLabel.text = nil;
self.retweetButton.selected = NO;
self.usernameLabel.text = nil;
}
There are a couple of things wrong with the code you have provided.
1 - Casting NSNumber to int
Retrieving favorited, which is presumably a number, from the dictionary will return an NSNumber which is a wrapper class for numbers. When you NSLog this it will print the result of it's description method, essentially printing out the underlying number.
When you cast an NSNumber to int you don't get the underlying number but the memory address in integer format.
See this code and some example output:
NSNumber *favorited = #(1);
NSLog(#"%#", favorited);
NSLog(#"%d", (int)favorited);
favorited = #(0);
NSLog(#"%#", favorited);
NSLog(#"%d", (int)favorited);
Outputs
2015-08-19 07:04:36.235 xctest[589:7545] 1
2015-08-19 07:04:36.236 xctest[589:7545] 18
2015-08-19 07:04:36.236 xctest[589:7545] 0
2015-08-19 07:04:50.720 xctest[589:7545] 2
To retrieve the underlying number it is necessary to use one of the appropriate *value methods such as integerValue or longValue.
2 - Calling select and deselect
Neither of these methods exist on UIButton unless you have created a custom subclass. To properly adjust the selected state of a button you need to use the selected property as you have done in the prepareForReuse method.
button.selected = YES; // or NO
Putting it all together
Taking the above information we can change part of the cell creation method as follows:
if ([favorited integerValue] == 1) {
cell.favoriteButton.selected = YES;
} else {
cell.favoriteButton.selected = NO;
}
if ([retweeted integerValue] == 1) {
cell.retweetButton.selected = YES;
} else {
cell.retweetButton.selected = NO;
}
I think the issue is with
(int)favorited == 1
Just use [favorited intvalue] things will be fine.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
this is my #{eventTime:eventCount}:
LYQMemoVC.m:196 dic :{
"2019-01-12" : "2",
"2019-02-20" : "1",
"2019-01-13" : "1",
"2019-02-10" : "1",
"2019-01-14" : "1"
}
issue:
event not 2019-02-09,but cell have badge... as this the same location will have badge. not event but appear badge.
the backgroundColor for cell is well, but the badge bug.
(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSString *identifier = [self.cellDic objectForKey:[NSString stringWithFormat:#"%#", indexPath]];
if (identifier == nil) {
identifier = [NSString stringWithFormat:#"ALCalendarCell%#", [NSString stringWithFormat:#"%#", indexPath]];
[_cellDic setValue:identifier forKey:[NSString stringWithFormat:#"%#", indexPath]];
[self registerClass:[ALCalendarCell class] forCellWithReuseIdentifier:identifier];
}
ALCalendarCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
cell.backgroundColor = [UIColor whiteColor];
if(indexPath.section == 0) {
cell.weekDay = self.titles[indexPath.row];
} else {
ALCalendarDate *date = self.dates[indexPath.row];
cell.date = date;
NSString *dateString;
if (date.isLastMonth) {
dateString = [[ALCalendarHelper lastYearAndMonth:self.yearAndMonth] stringByAppendingFormat:#"-%02zd",date.date.integerValue];
} else if (date.isNextMonth) {
dateString = [[ALCalendarHelper nextYearAndMonth:self.yearAndMonth] stringByAppendingFormat:#"-%02zd",date.date.integerValue];
} else {
dateString = [self.yearAndMonth stringByAppendingFormat:#"-%02zd",date.date.integerValue];
}
if ([self.config.heightlightDates containsObject:dateString]) {
cell.backgroundColor = self.config.hl_backgroundColor;
cell.layer.cornerRadius = self.config.hl_backgroundCornerRadius.floatValue;
cell.dateLabel.textColor = self.config.hl_textColor;
[self.config.eventDictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
if ([key isEqualToString:dateString]) {
cell.badge.badgeValue = [obj intValue];
cell.badge.backgroundColor = [UIColor lightGrayColor];
cell.badge.hidden = NO;
}
}];
}
if ([self.config.selectedDates containsObject:dateString]) {
cell.backgroundColor = self.config.sel_backgroundColor;
cell.layer.cornerRadius = self.config.sel_backgroundCornerRadius.floatValue;
cell.dateLabel.textColor = self.config.sel_textColor;
[self.config.eventDictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
if ([key isEqualToString:dateString]) {
cell.badge.badgeValue = [obj intValue];
cell.badge.backgroundColor = Config_Main_Color;
cell.badge.hidden = NO;
}
}];
}
}
return cell;
}
If I understand correctly, your badge is persistent across cell 're-uses'.
You want to hide and show the badge according to the date.
In your cellForItemAtIndexPath function you check for the following:
if ([key isEqualToString:dateString]) {
cell.badge.badgeValue = [obj intValue];
cell.badge.backgroundColor = Config_Main_Color;
cell.badge.hidden = NO;
}
and the last line un-hides your cell.badge. You never actually hide your badge again. And since you're reusing cells, there is no default value.
Your code should probably look somewhat like the following (copy to both if-statements):
if ([key isEqualToString:dateString]) {
cell.badge.badgeValue = [obj intValue];
cell.badge.backgroundColor = Config_Main_Color;
cell.badge.hidden = NO;
}
else {
cell.badge.badgeValue = 0;
cell.badge.hidden = YES;
}
First of all: is there a reason why you are managing all of the cell's properties in the view controller's cellForRowAtIndexPath: method instead of the cell ifself? This is not a very good approach, because only the cell should know what to do with its own properties (you give the cell the number, then it is the cell that decides what to do with it - show a badge, play a sound or perhaps shout out "TWENTY-FOUR!"). For instance, if in the future you need to use the same cell in another view controller, you shouldn't need to rewrite all of that code - which is what you'll need to do with your approach.
Anyway, apparently you are not resetting the cell's badge value in its prepareForReuse method.
Try implementing it this way (in the cell's .m file):
-(void)prepareForReuse {
[super prepareForReuse];
self.badge.badgeValue = 0;
}
I am using the google places api to search for nearby restaurants. Each restaurant is displayed in a cell in a UITableView. The return response is in the JSON format. Of the the things the JSON contains is a decimal number that represents the rating of the restaurant. I want to display the rating in the cells. However sometimes there is no rating for the restaurant and the value is (null). So I added a check in the cellForRowAtIndexPath method that checks if the value of the rating is null or not.
if([dict valueForKey:kResponseRating] != [NSNull null])
{
NSNumber *rating = [dict valueForKey:kResponseRating];
[cell displayRating:rating];
}
else
{
NSLog(#"Value of rating is null");
}
When I run the application the tableView still crashes as soon as a null value is returned and the string "Value of rating is null" is NOT printed. So its not going into the else statement even tho the value in the json is null.
Ok so I checked if the return value is of type NSString class and its not. Here is what i did in the same method:
if([[dict objectForKey:kResponseRating] isKindOfClass:[NSString class]])
{
NSLog(#"The return response is of type NSString");
}
And it did not go into if statement.
Here is the method that calculates the rating and posts it. The method takes the rating rounds it to the nearest .5 and then displays it as stars out of 5.
-(void)displayRating:(NSNumber*)rating{
double rate = [rating doubleValue];
rate = round(rate * 2.0) / 2.0;
int counter = 0;
double compareVar = 1.0;
while(counter <= 4){
if(rate == 0.0)
{
imgRating[counter] = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"starempty.png"]];
[self.contentView addSubview:imgRating[counter]];
}
else
{
if(compareVar < rate)
{
imgRating[counter] = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"starfill.png"]];
[self.contentView addSubview:imgRating[counter]];
}
else if(compareVar == rate)
{
imgRating[counter] = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"starfill.png"]];
[self.contentView addSubview:imgRating[counter]];
}
else
{
if(compareVar - rate == 0.5)
{
imgRating[counter] = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"starhalffill.png"]];
[self.contentView addSubview:imgRating[counter]];
}
else
{
imgRating[counter] = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"starempty.png"]];
[self.contentView addSubview:imgRating[counter]];
}
}
counter++;
compareVar = compareVar + 1.0;
}
}
NSLog(#"This is rate: %f", rate);
}
Is a line of code in this method causing a crash?
Try the below check
if(![dict objectForKey:kResponseRating] || [dict objectForKey:kResponseRating] == [NSNull null]) {
NSLog(#"Either the key doesn't exist or the value is null");
}
else {
// Covert and set the rating here!
}
This should do it.
if ([[dictionary valueForKey:#"key"] isKindOfClass:[NSNull class]] || ![dict valueForKey:#"key"]){
// Key doesn't exist or equals <null>
}
else{
// Key exist
}
And I'm pretty sure there are plenty of answers to this question on stack overflow. You should try looking if there is an answers to your question before creating a new one.
Anyway, I hope this helps
I've been brought in on this project where the previous developers made custom table cells and headers by using xib files and then registering the nibs like so:
[self.accountTable registerNib:[UINib nibWithNibName:kNonATITableViewCellLandscapeNib bundle:[NSBundle mainBundle]] forCellReuseIdentifier:kNonATITableViewCellLandscapeIdentifier];
[self.accountTable registerNib:[UINib nibWithNibName:kNonATITableHeaderLandscapeNib bundle:[NSBundle mainBundle]] forCellReuseIdentifier:kNonATITableHeaderLandscapeId];
The header files have buttons in them and uiimageviews. The buttons are for sorting, the uiimageviews for an arrow icon to show you the direction of the sort (asc, desc). All the buttons and imageviews are IBOutlets. All the buttons are linked to an IBAction:
- (IBAction)sortButtonTouched:(id)sender;
The file also has two other properties:
#property (nonatomic, assign) SortType currentSortingOption;
#property (nonatomic, strong) UIButton* btnLastTouched;
Here is sortButtonTouched:
- (IBAction)sortButtonTouched: (UIButton*) buttonTouched {
if (!self.btnLastTouched) {
self.btnLastTouched = buttonTouched;
}
NSString* strFieldToSort;
UIImageView* ivSortImage;
NSArray* arrSortIcons = [[NSArray alloc] initWithObjects:self.ivAccountSort,self.ivNameSort, self.ivAddressSort, self.ivCitySort, self.ivZipSort, self.ivLastCallSort, self.ivMileageSort, nil];
//get the image for the button selected
if (buttonTouched.tag == 0) {
strFieldToSort = #"customerNumber";
ivSortImage = self.ivAccountSort;
} else if (buttonTouched.tag == 1) {
strFieldToSort = #"customerName";
ivSortImage = self.ivNameSort;
} else if (buttonTouched.tag == 2) {
strFieldToSort = #"address";
ivSortImage = self.ivAddressSort;
} else if (buttonTouched.tag == 3) {
strFieldToSort = #"city";
ivSortImage = self.ivCitySort;
} else if (buttonTouched.tag == 4) {
strFieldToSort = #"zip";
ivSortImage = self.ivZipSort;
} else if (buttonTouched.tag == 5) {
strFieldToSort = #"lastCallDate";
ivSortImage = self.ivLastCallSort;
} else if (buttonTouched.tag == 6) {
strFieldToSort = #"mileage";
ivSortImage = self.ivMileageSort;
}
//set the sort option and add icon
if (!self.currentSortingOption) {
self.currentSortingOption = SORT_ASC;
[ivSortImage setImage:[UIImage imageNamed:Ascending_Icon]];
} else {
if (![self.btnLastTouched isEqual:buttonTouched]) {
self.currentSortingOption = SORT_ASC;
[ivSortImage setImage:[UIImage imageNamed:Ascending_Icon]];
} else {
if (self.currentSortingOption == SORT_ASC) {
self.currentSortingOption = SORT_DESC;
[ivSortImage setImage:[UIImage imageNamed:Descending_Icon]];
} else {
self.currentSortingOption = SORT_ASC;
[ivSortImage setImage:[UIImage imageNamed:Ascending_Icon]];
}
}
}
//show and hide
for(int i=0; i<arrSortIcons.count; i++) {
UIImageView* ivThisImage = [arrSortIcons objectAtIndex:i];
if (buttonTouched.tag == i) {
[UIView animateWithDuration:.25 animations:^(void) {
ivThisImage.alpha = 1.0;
}];
} else {
[UIView animateWithDuration:.25 animations:^(void) {
ivThisImage.alpha = 0.0;
}];
}
}
//call back to routing view controller and sort results based on sort order and field selected
NSDictionary* dictUserData = [[NSDictionary alloc] initWithObjectsAndKeys:
#"Sort Non-ATI", #"Action",
strFieldToSort, #"Field To Sort",
[NSNumber numberWithLong:self.currentSortingOption], #"Sortng Option",
nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"rvc" object:self userInfo:dictUserData];
self.btnLastTouched = buttonTouched;
}
And the notification fires this method:
- (void) sortNonATIResults : (NSDictionary*) dictSortParams {
if (self.arrNonATIResults.count > 0) {
NSString* sortKey = [dictSortParams objectForKey:#"Field To Sort"];
//change the field to sort to match the customerInfo object properties...
NSNumber* numSortType = [dictSortParams objectForKey:#"Sortng Option"];
BOOL isAsc = YES;
if ([numSortType intValue] == 2) {
isAsc = NO;
}
NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:isAsc];
NSArray* arrSortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
NSArray* arrSortedNonATIResults = (NSArray*)[self.arrNonATIResults sortedArrayUsingDescriptors:arrSortDescriptors];
self.arrNonATIResults = [arrSortedNonATIResults mutableCopy];
self.arrDatasource = self.arrNonATIResults;
[self.accountTable reloadData];
}
}
There are two problems right now. The icons are not showing up if the notification is sent. Comment out the notification and they function as expected. The other problem is that the property currentSortingOption doesn't retain it's value. I think both issues are related but I am not 100% sure. When the tableview is reloaded, does the header get instantiated again? This would make sense to me since then the uiimageviews would be reset with no image and the property would lose it's value and reset to 0 (it is the value of a typedef).
So, I am correct, how can I resolve this and if not, what could be causing the problems?
Thanks
OK, sorry for posting and then solving my problem right away, I guess sometimes you just need to write out the problem to find the solution. All I needed to do was not reload the table but just reload the rows. Here's the updated method:
(void) sortNonATIResults : (NSDictionary*) dictSortParams {
if (self.arrNonATIResults.count > 0) {
NSString* sortKey = [dictSortParams objectForKey:#"Field To Sort"];
//change the field to sort to match the customerInfo object properties...
NSNumber* numSortType = [dictSortParams objectForKey:#"Sortng Option"];
BOOL isAsc = YES;
if ([numSortType intValue] == 2) {
isAsc = NO;
}
NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:isAsc];
NSArray* arrSortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
NSArray* arrSortedNonATIResults = (NSArray*)[self.arrNonATIResults sortedArrayUsingDescriptors:arrSortDescriptors];
self.arrNonATIResults = [arrSortedNonATIResults mutableCopy];
self.arrDatasource = self.arrNonATIResults;
dispatch_async(dispatch_get_main_queue(), ^{
NSMutableArray *indexPathArray = [[NSMutableArray alloc] init];
for (NSInteger section = 0; section < [self.accountTable numberOfSections]; ++section)
{
for (NSInteger row = 0; row < [self.accountTable numberOfRowsInSection:section]; ++row)
{
[indexPathArray addObject:[NSIndexPath indexPathForRow:row inSection:section]];
}
}
[self.accountTable reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationNone];
[self.accountTable scrollsToTop];
});
}
}
I have dropped my code into a situation where I need to call UITableView data source methods written in some UIViewController class before a particular view is presented so that the cells get prepopulated and I can set a BOOL that the data in the not present viewController class is valid or not. I may explain it in more detail if required, but I wanted to know if its possible to do that. If yes, then how to do it? .. as a particular set of my code written after [tableView reloadData] is dependent on running the dataSource methods of UITableView. Please throw some light on this, if needs to be handled in a specific thread?
Following is the case where I call reloadData. Note: This is happening in another class when basicFactsViewController's viewWillAppear method has not been called yet:
- (BOOL) isComplete {
dispatch_async(dispatch_get_main_queue(), ^{
[basicFactsViewController.tableView reloadData];
});
return basicFactsViewController.isComplete && selectedVehicleId && selectedMakeId && selectedModelId && selectedYearId && selectedTrimId;
}
Now basicFactsViewController.isComplete is checked in this method:
- (BOOL) isComplete {
[self collectKeyHighlights];
return _isComplete;
}
Now the dictionary "tableCells" in the method below uses the cells population to check whether all features have been completed or not:
- (NSDictionary *) collectKeyHighlights {
NSMutableDictionary *key_highlights_update = [NSMutableDictionary new];
NSMutableDictionary *cell_highlight_update = [NSMutableDictionary new];
if(visible_key_highlights.count == 0) _isComplete = YES;
_isComplete = YES;
__block NSMutableArray *reloadCellAtIndexPathSet = [[NSMutableArray alloc] init];
[visible_key_highlights enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSDictionary *feature = (NSDictionary *)obj;
UITableViewCell *cell = [self.tableCells objectForKey:[NSIndexPath indexPathForRow:idx inSection:0]];
if(cell) {
if([cell isKindOfClass:[DRColorSelectionTableViewCell class]]) {
NSInteger selectedIndex = ((DRColorSelectionTableViewCell *)cell).selectedIndex;
NSInteger numberOfSegments = ((DRColorSelectionTableViewCell *)cell).numberOfSegments;
if(selectedIndex > -1 ) {
NSArray *dataValues = [[visible_key_highlights objectAtIndex:idx] objectForKey:#"data_values"];
NSDictionary *colorData;
BOOL reloadCellForIndexPath = NO;
if (numberOfSegments == selectedIndex) {
colorData = #{ #"normalized" : #"user_defined", #"isother" : #YES, #"hexcode":#"#FFFFFF", #"actual":((DRColorSelectionTableViewCell *)cell).otherColorTextField.text};
reloadCellForIndexPath = YES;
}
else{
colorData = [dataValues objectAtIndex:selectedIndex];
}
[key_highlights_update setObject:colorData forKey:[feature objectForKey:#"name"]];
[cell_highlight_update setObject:colorData forKey:[feature objectForKey:#"name"]];
if (![colorData isEqual:[prevSelections objectForKey:[feature objectForKey:#"name"]]]) {
[reloadCellAtIndexPathSet addObject:((DRColorSelectionTableViewCell *)cell).indexPath];
}
//if (reloadCellForIndexPath) {
//}
} else {
_isComplete = NO;
}
} else if([cell isKindOfClass:[DRInputTableViewCell class]]) {
NSString *textInput = ((DRInputTableViewCell *)cell).inputTextField.text;
if([textInput length]) {
[key_highlights_update setObject:[NSString toSnakeCase:textInput] forKey:[feature objectForKey:#"name"]];
[cell_highlight_update setObject:textInput forKey:[feature objectForKey:#"name"]];
}else {
_isComplete = NO;
}
} else if([cell isKindOfClass:[DRPickerTableViewCell class]]) {
NSString *textInput = ((DRPickerTableViewCell *)cell).inputField.text;
if([textInput length]) {
[key_highlights_update setObject:[NSString toSnakeCase:textInput] forKey:[feature objectForKey:#"name"]];
[cell_highlight_update setObject:textInput forKey:[feature objectForKey:#"name"]];
} else {
_isComplete = NO;
}
} else if([cell isKindOfClass:[DRSwitchTableViewCell class]]) {
// send this everytime for now
BOOL isSelected = ((DRSwitchTableViewCell *)cell).toggleButton.selected;
[key_highlights_update setObject:[NSNumber numberWithBool:isSelected] forKey:[feature objectForKey:#"name"]];
[cell_highlight_update setObject:[NSNumber numberWithBool:isSelected] forKey:[feature objectForKey:#"name"]];
}
}
else{
_isComplete = NO;
}
}];
prevSelections = cell_highlight_update;
if ([reloadCellAtIndexPathSet count]) {
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:reloadCellAtIndexPathSet withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
}
return key_highlights_update;
}
Now here since
[tableView reloadData]
is not calling cellForRowAtIndePath:, hence, tableCells is not getting populated, hence, I am always getting _isComplete = NO.
If I understand correctly, there is processing being done when the tableview loads (calls it's dataSource methods) and you want to trigger that early to use its results. Calling [basicFactsViewController.tableView reloadData]; early won't work if the basicFactsViewController hasn't been displayed yet. If basicFactsViewController is a UIViewController and has the default view and the tableView property is a subview of that standard view, then (if I remember correctly) the tableView property will be nil until the basicFactsViewController has been displayed. A shortcut around that is to access the viewController's view property and cause it to initialize (viewDidLoad and all that). You can do that by simply messaging the viewController: [basicFactsViewController view].
If I've been right so far I'm fairly confident that will initialize the tableView property. But I'm not sure if it will cause the table view to load its data. And even if it does work, it's definitely not the best solution to the piece of code you're trying to architect. Apple's design for UIKit has been focused on the model/view/controller pattern and it's easier to go with the flow and do the same. I imagine that you could move the processing that is in the data source methods for the tableView out into another class (or maybe even the same class), and call that method to get everything ready for both the tableView and any other checks that you have, storing the data in dictionaries and arrays in such a way that you can easily load them by index into the tableView when cellForIndex is called.
I am having the [__NSArrayM insertObject:atIndex:]: object cannot be nil crash when I test the app on my device, but not on the iOS simulator.
Here's what going on:
I am managing 5 UITextField on a View Controller, then I am passing the text of each UITextField to a another View Controller via an NSString using an IBAction (when I press the button, it crashes).
TextViewController
- (IBAction)choicebutton:(id)sender {
AnswerViewController *AVC = [self.storyboard instantiateViewControllerWithIdentifier:#"AnswerViewController"];
AVC.stringFromChoice1 = self.choice1.text;
AVC.stringFromChoice2 = self.choice2.text;
AVC.stringFromChoice3 = self.choice3.text;
AVC.stringFromChoice4 = self.choice4.text;
AVC.stringFromChoice5 = self.choice5.text;
[self presentViewController:AVC animated:YES completion:nil];
}
Then on the AnswerViewController, I am creating an NSMutableArray and randomizing the NSStrings to be displayed on a UILabel.
AnswerViewController
- (void)viewDidLoad
{
self.choiceAnswers1 = [[NSMutableArray alloc] initWithCapacity:5];
if(![self.stringFromChoice1 isEqualToString:#""])
{
[self.choiceAnswers1 addObject:self.stringFromChoice1];
}
if(![self.stringFromChoice2 isEqualToString:#""])
{
[self.choiceAnswers1 addObject:self.stringFromChoice2];
}
if(![self.stringFromChoice3 isEqualToString:#""])
{
[self.choiceAnswers1 addObject:self.stringFromChoice3];
}
if(![self.stringFromChoice4 isEqualToString:#""])
{
[self.choiceAnswers1 addObject:self.stringFromChoice4];
}
if(![self.stringFromChoice5 isEqualToString:#""])
{
[self.choiceAnswers1 addObject:self.stringFromChoice5];
}
int index = arc4random() % [self.choiceAnswers1 count];
self.choiceanswer.text = self.choiceAnswers1[index];
self.choiceanswer1.text = self.choiceAnswers1[index];
}
I've set it up this way in case the user doesn't fill all of the UITextFields, does this have to do anything with the crash? I can't figure this one out, please help!
Thanks!
Don’t use compare: against the empty string—it doesn’t catch the case where your string is nil and not #“”. Those are two distinct cases.
Instead of this:
if(![self.stringFromChoice1 isEqualToString:#""])
{
[self.choiceAnswers1 addObject:self.stringFromChoice1];
}
use this:
if (self.stringFromChoice1.length)
[self.choiceAnswers1 addObject:self.stringFromChoice1];
Since in C any non-0 value is true, and since sending a message to a nil object always returns 0, this catches all the cases. And is less wordy.
Less code is better code!
Change you viewDidLoad something like this.
- (void)viewDidLoad
{
self.choiceAnswers1 = [[NSMutableArray alloc] init];
if(self.stringFromChoice1.length > 0)
{
[self.choiceAnswers1 addObject:self.stringFromChoice1];
}
if(self.stringFromChoice2.length > 0)
{
[self.choiceAnswers1 addObject:self.stringFromChoice2];
}
if(self.stringFromChoice3.length > 0)
{
[self.choiceAnswers1 addObject:self.stringFromChoice3];
}
if(self.stringFromChoice4.length > 0)
{
[self.choiceAnswers1 addObject:self.stringFromChoice4];
}
if( self.stringFromChoice5.length > 0)
{
[self.choiceAnswers1 addObject:self.stringFromChoice5];
}
int index = arc4random() % [self.choiceAnswers1 count];
self.choiceanswer.text = self.choiceAnswers1[index];
self.choiceanswer1.text = self.choiceAnswers1[index];
}
Let me know it that helps.. :)