NSMutableArray index mixed up - iphone

I'm currently trying the iCarousel Multiple Carousel example.
Here in my array, I've add images with NSMutableDictionary:
I have two of these: ( myImages and myImages2 for my two slot in carousel loaded in ViewDidLoad)
self.myImages = [NSMutableArray array];
for(int i = 0; i <= 10; i++)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *savedPath = [documentsDir stringByAppendingPathComponent:[NSString stringWithFormat:#"myImages%d.png", i]];
if([[NSFileManager defaultManager] fileExistsAtPath:savedPath]){
NSMutableDictionary *container = [[NSMutableDictionary alloc] init];
[container setObject:[UIImage imageWithContentsOfFile:savedPath] forKey:#"image"];
[container setObject:[NSNumber numberWithInt:i] forKey:#"index"];
[images addObject:container];
[container release]; // if not using ARC
}
}
in my iCarousel:
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
if (carousel == carousel1)
{
NSDictionary *obj = [items1 objectAtIndex:index];
view = [[UIImageView alloc] initWithImage:[obj objectForKey:#"items1"]];
view.tag = index;
}else
{
NSDictionary *obj = [items2 objectAtIndex:index];
view = [[UIImageView alloc] initWithImage:[obj objectForKey:#"items2"]];
view.tag = index;
}
return view;
}
In another View, these arrays are also loaded, the user has a chance to pick an image to compare to with,
when an user pick an image an int equivalent to its tag is pass to where my two Carousel is.
Here is how I compare them:
NSInteger image = [prefs integerForKey:#"image"];
NSInteger image1 = [prefs integerForKey:#"image2"];
if (image == [(UIImageView*)[self.carousel1 currentItemView] tag] || image2= [(UIImageView*)[self.carousel2 currentItemView] tag] || ) {
I delete an index this way:
NSInteger index = carousel1.currentItemIndex;
[carousel1 removeItemAtIndex:index animated:YES];
[items1 removeObjectAtIndex:index];
I think I'm deleting it the wrong away, because the index arent updated, what i wanted is to maintain its index not adjust like this images right here:
Deleting in NSMutableArray

If I understand what you are trying to do now, which is to move the two carousels until the middle one matches, then to not have the indexes simply go away, then you could just rather than removing the item from the array, fill the location you are trying to delete with a nil image (or a valid image with the backing of your choosing), and a tag stating it has already been matched.
This is all of course dependent on whether my understanding of what you want is valid.

Related

NSMutableArray Not Retaining Objects Outside Method [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
In my -viewDidLoad method, I initialize many NSMutableDictionaries, and add them to an initialized NSMutableArray declared via #property in the class header file. The relevant code is shown below. In short, I'm webscraping information from an HTML webpage.
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
_regionalDicts = [[NSMutableArray alloc] init];
for (int i = 0; i < [strings count]; i++) {
NSString *str = [strings objectAtIndex:i];
//Property parser:
if ([str rangeOfString:#"<td>"].location != NSNotFound) {
NSString *parsedTD1 = [str stringByReplacingOccurrencesOfString:#"<td>" withString:#""];
NSString *parsedTD2 = [parsedTD1 stringByReplacingOccurrencesOfString:#"</td>" withString:#""];
NSString *parsedTD3 = [parsedTD2 stringByReplacingOccurrencesOfString:#" " withString:#"\n"];
NSString *final = [parsedTD3 stringByReplacingOccurrencesOfString:#"\t" withString:#""];
//NSLog(#"Final string: %#", final);
if ([final isEqualToString:#""]) {
continue;
}
if (gotEventType == NO) {
gotEventType = YES;
[dict setObject:final forKey:#"type"];
continue;
}
if (gotRegional == YES && gotLocation == NO) {
gotLocation = YES;
[dict setObject:final forKey:#"location"];
continue;
}
if (gotLocation == YES && gotCity == NO) {
gotCity = YES;
NSString *cityToReturn = [final stringByReplacingOccurrencesOfString:#"\n" withString:#""];
[dict setObject:cityToReturn forKey:#"city"];
continue;
}
if (gotRegional == YES && gotEventType == YES && gotCity == YES && gotLocation == YES && gotURL == YES) {
gotRegional = NO;
gotEventType = NO;
gotCity = NO;
gotLocation = NO;
gotURL = NO;
NSLog(#"Regional: %#", [dict objectForKey:#"regional"]);
NSLog(#"Type: %#", [dict objectForKey:#"type"]);
NSLog(#"City: %#", [dict objectForKey:#"city"]);
//Testing to see if anything is nil
NSLog(#"Location: %#\n", [dict objectForKey:#"location"]);
if (!_regionalDicts) {
NSLog(#"Dict is nil");
}
[_regionalDicts addObject:dict];
NSLog(#"Objects in array: %u", [_regionalDicts count]);
NSMutableDictionary *tempDict = [_regionalDicts objectAtIndex:[_regionalDicts count]-1];
NSLog(#"Regional in array: %#", [tempDict objectForKey:#"regional"]);
[dict removeAllObjects];
continue;
}
It's clear that the generated dictionaries are generated and retained within the _regionalDicts mutable array, which is declared in the header file like this:
#property (strong, nonatomic) IBOutlet NSMutableArray *regionalDicts;
However, when I attempt to pass in information to table view cells in in the same class, the dictionaries' contents are null. There are as many objects within the array as dictionaries I am expecting, but they do not contain any content.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (_regionalDicts) {
NSMutableDictionary *dict = [_regionalDicts objectAtIndex:0];
NSLog(#"Setting label %#", [dict objectForKey:#"city"]);
[cell.textLabel setText:[dict objectForKey:#"regional"]];
}
return cell;
}
Returns:
2013-04-01 19:58:50.250 MatchScrape[53570:207] Setting label (null)
I can only imagine that a memory management issue is to blame. Why would the contents of a class array be nullified when accessed outside the scope of the method they are added in, but allow the array to retain the same count?
You seem to believe that adding the dictionary to the array doesn't actually add the dictionary to the array, but instead adds a copy of the dictionary. You're probably thinking of how it might work in a language like C++ — but that isn't how it works here. Remember, Objective-C objects are always accessed by reference: you never directly store the object itself in a variable or array — you're just shuffling around a pointer to the actual object, which usually lives on the heap.
So when you add _dict to the array, the one in the array is the very same object referenced by _dict. Anything you do to that dictionary — no matter what reference you use — will be reflected everywhere else that dictionary is referenced, because it's the same dictionary. You haven't made a copy of it. Thus, when you do [_dict removeAllObjects], that removes all the objects from the dictionary and you end up with an array that contains the same empty dictionary a bunch of times.

keysSortedByValueUsingSelector crashes but sortedArrayUsingSelector runs fine

I found a workaround myself, but still trying to understand the problem.
I created a Autocomplete text field with the use of uitableview which is hidden until textfield is edited. The UI part works fine. It's the searching for the results part that's the problem. I declared a local NSMutableDictionary to store my results because I wanted the results to be sorted by the key's values.
if I call keysSortedByValueUsingSelector on the dictionary directly, it crashes. However if I get the keys by [dict allKeys] first, then call sortedArrayUsingSelector, it works fine:
// This commented out line will crash
// NSArray *sortedKeysArray = [dict keysSortedByValueUsingSelector:#selector(compare:)];
// The next two lines runs fine.
NSArray *keyArray = [dict allKeys];
NSArray *sortedKeysArray = [keyArray sortedArrayUsingSelector:#selector(compare:)];
Here is the complete source code for the search method:
- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring
{
// Put anything that starts with this substring into the autocompleteUrls array
// The items in this array is what will show up in the table view
[autocomplete_symbol_array removeAllObjects];
rRSIAppDelegate *appDelegate = (rRSIAppDelegate *)([[UIApplication sharedApplication] delegate]);
NSString *input_str = [substring uppercaseString];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
int i = 0;
for(SymbolInfo *symbol_info in appDelegate.m_symbol_info_array)
{
i++;
NSString *info_str = [[[symbol_info.m_symbol uppercaseString] stringByAppendingString:#"|"] stringByAppendingString:[symbol_info.m_company_name uppercaseString]];
NSUInteger pos = [info_str rangeOfString:input_str].location;
if (pos != NSNotFound)
{
int tmp = pos * 10000 + i;
NSNumber *map_key = [[NSNumber alloc] initWithInt:tmp];
[dict setObject:symbol_info forKey:map_key];
}
}
// This commented out line will crash
// NSArray *sortedKeysArray = [dict keysSortedByValueUsingSelector:#selector(compare:)];
// The next two lines runs fine.
NSArray *keyArray = [dict allKeys];
NSArray *sortedKeysArray = [keyArray sortedArrayUsingSelector:#selector(compare:)];
for (NSNumber *key in sortedKeysArray)
{
SymbolInfo *symbol_info = [dict objectForKey:key];
[autocomplete_symbol_array addObject:symbol_info];
}
// NSLog(#"everything added: %d", [autocomplete_symbol_array count]);
[autocompleteTableView reloadData];
}
The NSMutableDictionary's method is:
- (void)setObject:(id)anObject forKey:(id < NSCopying >)aKey;
This means that the key should implement the NSCopying protocol.

UIImageView displaying

I'm using the Custom Picker by ray, when I press a button a picker is pop-ups then when image is chosen it will dismiss the picker and displayed the image in UIImageView. I put in the viewWillAppear but when I go to another ViewController the image chosen disappears. How to maintain the chosen in UIImageView to be displayed even after going to different View Controllers, only will it change if another image is chosen again.
- (void)viewWillAppear:(BOOL)animated {
secondView.image = _imagePicker.selectedImage;
}
- (IBAction)chooseCustomImageTapped:(id)sender {
_imagePicker = [[CustomImagePicker alloc] init];
_imagePicker.title = #"Choose Custom Image";
for(int i = 0; i <= 10; i++)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDir stringByAppendingPathComponent:[NSString stringWithFormat:#"Images%d.png", i]];
if([[NSFileManager defaultManager] fileExistsAtPath:savedImagePath]){
[_imagePicker addImage:[UIImage imageWithContentsOfFile:savedImagePath]];
}
}
[self presentModalViewController:_imagePicker animated:NO];
}
I think you should take your image in UIImage object just after selection done UIImage *image = _imagePicker.selectedImage;, and retain it till next change. Then set that image to your image view secondView.image = image;.
Did you alloc a new view controller when you go to the specified view controller? If so, when you go to a new view controller, you alloc it, so all the datas has been initalized.
use the pickerview delegate function.
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
// put your logic here.
NSUserDefaults *udf=[NSUserDefaults standardUserDefaults];
[udf setObject:#"Imagename" forKey:#"LastSelectImage"];
}
accordingly your image has change your image name here.

Removing UIImageView from UIScrollView

My app consists of an image gallery. It is a scroll view which displays pics retrieved from the sqlite db. User can scroll the images, add or delete images etc. I can add a picture to the gallery dynamically. But the problem comes when I need to implement the delete functionality. I use the following code but even after calling removeFromSuperView the image is not getting removed from the scrollview.
-(void)deleteDeck{
if(selectedEditDeck!=0){
[deck deleteSelectedDeck:selectedEditDeck]; //deleting from database
//problem starts here ***
[(UIImageView*)[decksGallery viewWithTag:selectedEditDeck-1]removeFromSuperview];
[self loadGallery];
selectedEditDeck=0;
//Ends here*****
[tableData release];
tableData=[NSMutableArray array];
[self showCardNamesinTable];
[aTableView reloadData];
}
I have already created the uiscrollview in the loadview method. Then to refresh the view after every deletion and addition of images so that I can display the updated gallery, I use the following piece of code:
-(void)loadGallery{ //Reloading all for adding a single deck image.
//Database part****
NSString *sqlStr = [NSString stringWithFormat:#"select first_card from decksTable"];
char *sql = (char*)[sqlStr UTF8String];
kidsFlashCardAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSMutableArray *galleryImagesArray=[appDelegate.dbConnection fetchColumnFromTable:sql col:0];
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *docDirectory = [sysPaths objectAtIndex:0];
numberofImages = [galleryImagesArray count];
printf("number is %d",numberofImages);//Database part of code ends here
//In the following fragment of code I add images to UIscrollView
for (int i = 0; i < [galleryImagesArray count]; i++) {
CGFloat yOrigin = i * 65;
NSString *filePath = [NSString stringWithFormat:#"%#/%#", docDirectory,[galleryImagesArray objectAtIndex:i]];
galleryImage = [[UIImageView alloc] initWithFrame:CGRectMake(yOrigin+140, 15,50,50 )];
//galleryImage.tag=[galleryImagesArray count];
galleryImage.tag=i;
printf("THE TAG IS %d",galleryImage.tag);
galleryImage.clipsToBounds=YES;
galleryImage.layer.cornerRadius=11.0;
galleryImage.backgroundColor=[UIColor clearColor];
galleryImage.image =[UIImage imageWithContentsOfFile:filePath];
[decksGallery addSubview:galleryImage];
[galleryImage release];
}
decksGallery.contentSize = CGSizeMake(115*[galleryImagesArray count], 80);
//[decksGallery reloadInputViews];
Make sure your [decksGallery viewWithTag:selectedEditDeck-1] is not returning nil and the image was actually deleted from your db before the refresh code running.
In addition, you are setting imageView.tag = i; in your creation code, since the i would be 0 which is the tag's default value for every UIView, you'd better fix your creation code as well.
If you just want to remove the image from your imageView, you can also do imageView.image = nil;
UIImageView*imageView = (UIImageView*)[decksGallery viewWithTag:selectedEditDeck-1];
[imageView removeFromSuperview];
imageView = nil;

Dealing with editable items in a filtered UITable with an NSMutableArray copy

I have a UITable with a datasource that is set to a 'copy' of the original data. I use this copy to displayed filtered results (either 'All' or only those that are 'checked' with a UISwitch in each row). My logic for doing the filtering is here:
-(void)filterItems {
[tableData removeAllObjects];
if (checkedOrNotSwitch.selectedSegmentIndex == 0) {
[tableData addObjectsFromArray:self.defaultChecklistItemsArray];
} else {
for (NSMutableDictionary *sectionDict in self.defaultChecklistItemsArray) {
NSMutableArray *newItemsArray = [[NSMutableArray alloc] init];
[newItemsArray removeAllObjects];
for (NSMutableDictionary *itemDict in [sectionDict objectForKey:#"categoryItems"]) {
if ([[itemDict objectForKey:#"isComplete"] boolValue]) {
[newItemsArray addObject:itemDict];
}
}
if ([newItemsArray count] > 0) {
NSMutableDictionary *newSectionDict = [[NSMutableDictionary alloc] initWithDictionary:sectionDict];
[newSectionDict setObject:newItemsArray forKey:#"categoryItems"];
[tableData addObject:newSectionDict];
[newSectionDict release];
}
}
}
[checklistTable reloadData];
}
The filtering itself now works correctly. In my custom cell, each row has a UISwitch. The switch runs this function when its changed:
-(IBAction) switchValueChanged{
NSIndexPath *indexPath = [(UITableView *)self.superview indexPathForCell: self];
[self.parentController updateCompletedStatusAtIndexPath:indexPath toStatus:isCompleted.on];
}
The function above is in the class for the tableviewcell itself. The function I call in the superview is this:
-(void)updateCompletedStatusAtIndexPath:(NSIndexPath *)indexPath toStatus:(BOOL)status{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSMutableDictionary *currentsection = [[NSMutableDictionary alloc] initWithDictionary:[tableData objectAtIndex:section]];
NSMutableArray *itemsArray = [[NSMutableArray alloc] initWithArray:[currentsection objectForKey:#"categoryItems"] copyItems:YES];
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] initWithDictionary:[itemsArray objectAtIndex:row]];
NSLog(#"BOOL = %#\n", (status ? #"YES" : #"NO"));
[tempDict setValue:[NSNumber numberWithBool:status] forKey:#"isComplete"];
[itemsArray replaceObjectAtIndex:row withObject:tempDict];
[currentsection setValue:itemsArray forKey:#"categoryItems"];
[tableData replaceObjectAtIndex:section withObject:currentsection];
[tempDict release];
[itemsArray release];
[currentsection release];
[checklistTable reloadData];
}
Before I implemented the filtering and used the logic above on self.defaultChecklistItemsArray directly, it worked and saved the data when the switch was flipped.
Now when I first enter the app, it loads the array of data from nsuserdefaults. I navigate to the view with the table and it displays the data correctly there with the UISwitches all in the correct position given the data (some on, some off). When I tap one of the switches, then click the segmentedcontrol that does the filtering, the data reverts back to the state it was loaded in, implying that the flipping of the switch did not actually effect the data at all (even though I don't think I did a deep copy anywhere here so I figured it should be doing the right thing). Any suggestions?