Refresh mainviewController after changes objective-c - objective-c

I want to reload(refresh) my mainviewcontroller after changes. I add some data to data model and after save operation I put buttons to data elements on my main view. In second controller I make a edition section in which I change or delate data from base. My question is: How can I reload main view after delating element from base. My code for creating buttons is in mainviewcontroller:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Destination" inManagedObjectContext:_managedObjectContext];
[request setEntity:entity];
NSError *error = nil;
mutableFetchResults = [[_managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
CGFloat y = 130.;
for (int i = 0; i < [mutableFetchResults count]; i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:[NSString stringWithFormat:#"ikonki%d.png",i]] forState:UIControlStateNormal];
[button setTitle:#"Test" forState:UIControlStateNormal];
NSLog(#"%#",_destination3.nazwa);
[button setTitleColor: [UIColor whiteColor] forState: UIControlStateNormal];
[button setEnabled:YES];
[button addTarget:self
action:#selector(buttonHandler:)
forControlEvents:UIControlEventTouchUpInside];
button.tag = i;
button.frame = CGRectMake(x, y, 64 , 64);

Do you know NSFetchedResultsController? Go to documentation and look at DataSectionTitles and iPhoneCoreDataRecipes samples. Here you can find how to use this class. Basically this class gets your fetch request, listens for changes and if you delete / insert / update / ... objects in your NSManagedObjectContext it triggers delegate methods where you can update your view.

Related

In Objective-C, how can I make this code efficient?

[self.menuBtn1 setImage:[UIImage imageNamed:#"menu1.png"] forState:UIControlStateNormal];
[self.menuBtn2 setImage:[UIImage imageNamed:#"menu2.png"] forState:UIControlStateNormal];
[self.menuBtn3 setImage:[UIImage imageNamed:#"menu3.png"] forState:UIControlStateNormal];
[self.menuBtn4 setImage:[UIImage imageNamed:#"menu4.png"] forState:UIControlStateNormal];
[self.menuBtn5 setImage:[UIImage imageNamed:#"menu5.png"] forState:UIControlStateNormal];
[self.menuBtn6 setImage:[UIImage imageNamed:#"menu6.png"] forState:UIControlStateNormal];
[self.menuBtn7 setImage:[UIImage imageNamed:#"menu7.png"] forState:UIControlStateNormal];
This Code is very inefficient. But I think it can be efficient with forsyntax. However I don't know how can I code self.menuBtn%d with for. In Objective-C, How can I code this?
This access the button properties dynamically so you don't need an array. This only works if the buttons have already been initialized (they are if they're IBOutlets)
NSString *imageName;
NSString *buttonName;
UIImage *image;
for (int i = 1; i < 8; i++) {
//#autoreleasepool {
imageName = [NSString stringWithFormat:#"menu%d", i];
buttonName = [NSString stringWithFormat:#"menuBtn%d", i];
image = [UIImage imageNamed:imageName];
UIButton *button = (UIButton *)[self valueForKey:buttonName];
if (button)
[button setImage:image forState:UIControlStateNormal];
/*
If you needed to scale this to say 1000 images, you can uncomment the first
and last line in the for-loop which will automatically release the variables
each iteration so the memory consumption doesn't spike.
*/
//}
}
One solution might be to set the tag of all your buttons to some value (e.g. 100 + button number), then to try:
for (UIButton *aButton in self.view.subviews)
{
if ((aButton.tag >= 100 and aButton.tag < 107))
[aButton setImage:[UIImage imageNamed:[NSString stringWithFormat:#"menu%d.png",aButton.tag]] forState:UIControlStateNormal];
}
First add the buttons to the array and the use for loop like this:
NSArray *array=[NSArray arrayWithObjects:menuBtn1,menuBtn2,menuBtn3,menuBtn4,menuBtn5,menuBtn6menuBtn7,nil];
int i=1;
for(UIButton *aButton in array){
[aButton setImage:[UIImage imageNamed:[NSString stringWithFormat:#"menu%d.png",i++]] forState:UIControlStateNormal];
}
NSString *menubutton;
NSMutableArray *imagearray = [[NSMutableArray alloc]initWithObjects:#"image1.png",#"image2.png",#"image3.png", nil];
for(int i=0; i<[imagearray count]; i++)
{
menubutton = [NSString stringWithFormat:#"menuBtn%d",i];
UIButton *button = (UIButton *)[self valueForKey:menubutton];
[button setImage:[UIImage imageNamed:[NSString stringWithFormat:#"%#",[imagearray objectAtIndex:i]]] forState:UIControlStateNormal];
}

specific title for each button in UIScrollView

I have an UIWebView page with one UIScrollView, inside of my UIScrollView I have UIImage and buttons
I want to set specific title for each button from my xml file, Would you please give me some hint for implementing this?
rightnow I can get the first name from xml but it"s set for all
my scrollView with Button and images:
const NSUInteger kNumImages = 5;
scrollView1.pagingEnabled = YES;
// load all the images
NSUInteger i;
for (i = 1; i<= kNumImages; i++)
{
NSString *imageName = [NSString stringWithFormat:#"image%d.jpg", i];
UIImage *image = [UIImage imageNamed:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.userInteractionEnabled = YES;
CGRect rect = imageView.frame;
rect.size.height = kScrollObjHeight;
rect.size.width = kScrollObjWidth;
imageView.frame = rect;
imageView.tag = i;
[scrollView1 addSubview:imageView];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
appDelegate = (testAppDelegate *)[[UIApplication sharedApplication] delegate];
Presentation1Name *aSlide = [appDelegate.books objectAtIndex:0];
NSLog(#" %#", aSlide.slideLabel );
[btn setTitle:[NSString stringWithString:aSlide.slideLabel]
forState:UIControlStateNormal];
btn.frame = rect;
[btn setTag:i];
[btn addTarget:self action:#selector(buttonClick:)
forControlEvents:UIControlEventTouchUpInside];
[imageView addSubview:btn];
}
[self layoutScrollImages];
}
for adding title for all button I'm using code
[btn setTitle:[NSString stringWithString:aSlide.slideLabel]
forState:UIControlStateNormal];
but for each button I want to have specific title from xml file
Thanks in advance!
Here is my xml file:
<Presentation label="presentation1">
<slides>
<slide index="0" label="slide1" identifier="Slide1Name" />
<slide index="1" label="something" identifier="Slide2Name" />
</slides>
</Presentation>
Edit:
When I add Presentation1Name *aSlide = [appDelegate.books objectAtIndex:0]; objectAtIndex to i I will get this error
when I add objectAtIndex: i
process terminated * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: ' -[NSPlaceholderString initWithString:]: nil argument'
** First throw call stack:
(0x1c95012 0x10d2e7e 0x1c94deb 0xae97f5 0xae9774 0x3d64 0x4723 0x10e6705 0x1d920 0x1d8b8 0xde671 0xdebcf 0xddd38 0x4d33f 0x4d552 0x2b3aa 0x1ccf8 0x1bf0df9 0x1bf0ad0 0x1c0abf5 0x1c0a962 0x1c3bbb6 0x1c3af44 0x1c3ae1b 0x1bef7e3 0x1bef668 0x1a65c 0x295d 0x2885 0x1)
libc++abi.dylib: terminate called throwing an exception
(lldb)
and it"s because of
-[NSPlaceholderString initWithString:]: nil argument'
after that I change 5 t0 2 since I have just 2 label in my xml file
const NSUInteger kNumImages= 2;
and also change for (i = 1; i<= kNumImages; i++) to
for (i = 0; i> kNumImages; i++)
but still it"not working correctly
My question is How can I do this
appDelegate.books count should be equal to kNumImages
[btn setTitle:[NSString stringWithFormat:#"MyButton %d", i] forState:UIControlStateNormal];
Store all button names in NSMutableArray and then later use it
For example like this:
NSMutableArray *arrNames = [NSMutableArray alloc]initWithObjects:#"Dog",#"Cat",......,nil]; //fill your array
[btn setTitle:[arrNames objectAtIndex:i] forState:UIControlStateNormal];
Second option is to use #Andrey Chernukha justed in his answer

Xcode allocation problems with UIImagaView keep growing

I load alot of images in my image gallery and in my thumbnail gallery, every time i press a button (section) i replace the images with the right seciont's images, all ok since the 6th-7th time i do this my app crash.
So i tried build with allocation tool and i see allocation memory growing up every time i press the button! i've been aspected to see a stack memory allocation not a growing one with
initWithContentOfFile.
What am i doing wrong?
for (UIView *view in [scroller subviews]) {
[view removeFromSuperview];
}
for (UIView *view in [thumbnail subviews]) {
[view removeFromSuperview];
}
for (int i=1; i<numeroimg+1; i++) {
UIImageView *imagen = [[[UIImageView alloc] initWithImage:[[UIImage alloc] initWithContentsOfFile:
[[NSBundle mainBundle]
pathForResource:[NSString stringWithFormat:#"%#%d",sezione,i]
ofType:#"jpg"]]]autorelease];
imagen.frame = CGRectMake((i-1)*1024, 0, 1024, 704);
[scroller addSubview:imagen];
UIButton *button = [[[UIButton alloc] initWithFrame:CGRectMake((i-1)*210, 30, 200, 150)]autorelease];
[button setImage:[[UIImage alloc] initWithContentsOfFile:
[[NSBundle mainBundle]
pathForResource:[NSString stringWithFormat:#"%#%d",sezione,i]
ofType:#"jpg"]] forState:UIControlStateNormal];
[button addTarget:self action:#selector(pagina:) forControlEvents:UIControlEventTouchUpInside];
button.tag = i;
[thumbnail addSubview:button];
}
What am i doing wrong?
You're using +alloc to create an image:
UIImageView *imagen = [[[UIImageView alloc] initWithImage:...
but you never release imagen.
Try to manually drain the autorelease pool
#autoreleasepool{
UIImageView *imagen = [[[UIImageView alloc] initWithImage:[[UIImage alloc] initWithContentsOfFile:
[[NSBundle mainBundle]
pathForResource:[NSString stringWithFormat:#"%#%d",sezione,i]
ofType:#"jpg"]]]autorelease];
imagen.frame = CGRectMake((i-1)*1024, 0, 1024, 704);
[scroller addSubview:imagen];
UIButton *button = [[[UIButton alloc] initWithFrame:CGRectMake((i-1)*210, 30, 200, 150)]autorelease];
[button setImage:[[UIImage alloc] initWithContentsOfFile:
[[NSBundle mainBundle]
pathForResource:[NSString stringWithFormat:#"%#%d",sezione,i]
ofType:#"jpg"]] forState:UIControlStateNormal];
[button addTarget:self action:#selector(pagina:) forControlEvents:UIControlEventTouchUpInside];
button.tag = i;
[thumbnail addSubview:button];
}

Difficulty with accessing list of URLs in XML file

I am trying to make an app that plays MP3 songs. My program flow is like this:
I have an XML file here in my website: http://jeewanaryal.web44.net/SongsXML/songsListXML.xml. It has song titles and the actual URL of those songs on the Internet. I have the following code for my Pop songs section:
NSString *urlString = #"http://jeewanaryal.web44.net/SongsXML/songsListXML.xml";
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
NSDictionary *dict = [XMLReader dictionaryForXMLData:data error:nil];
NSArray *arrayOfSongs = [[NSArray alloc] initWithArray:[[[dict objectForKey:#"list"] objectForKey:#"songs"] objectForKey:#"song"]];
StartStopSound = [UIButton buttonWithType:UIButtonTypeRoundedRect];
StartStopSound.frame = CGRectMake(60, 360, 200, 30);
[StartStopSound setTitle:#"बजाउनुहोस" forState:UIControlStateNormal];
[StartStopSound addTarget:self action:#selector(playSong) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:StartStopSound];
back = [UIButton buttonWithType:UIButtonTypeRoundedRect];
back.frame = CGRectMake(20, 320, 100, 30);
[back setTitle:#"पछाडीको गीत " forState:UIControlStateNormal];
[back addTarget:self action:#selector(playSong) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:back];
next = [UIButton buttonWithType:UIButtonTypeRoundedRect];
next.frame = CGRectMake(200, 320, 100, 30);
[next setTitle:#"अगाडीको गीत" forState:UIControlStateNormal];
[next addTarget:self action:#selector(playSong) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:next];
NSData *myData = [[NSData alloc] init ];
NSString *urlString1 = [[NSString alloc] init];
for (NSDictionary *fruitDict in arrayOfSongs) {
UILabel *songTitle = [[UILabel alloc] initWithFrame:CGRectMake(40, 200, 300, 40)];
songTitle.text = [NSString stringWithFormat:#"%#",[[fruitDict objectForKey:#"title"] objectForKey:#"text"]];
[self.view addSubview:songTitle];
urlString1 = [NSString stringWithFormat:#"%#",[[fruitDict objectForKey:#"url"] objectForKey:#"text"]];
//NSLog(#"\n\n -- URL STRING : %# \n\n",urlString);
}
myData = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString1]];
player = [[AVAudioPlayer alloc] initWithData:myData error:nil];
[player play];
[player numberOfLoops];
[player currentTime];
This works fine for a single song; that is, it only plays the last URL of my XML file. I want to make all songs to be played one by one, making a "Next" and "Previous" button on my app.
Will you please tell me how I can implement that? I am using XMLReader.h and XMLReader.m file to parse the data from XML into my app.
You would need to store arrayOfSongs somewhere in the class. The "back" and "next" buttons would need separate actions (e.g. playPreviousSong, playNextSong). These methods would then look something like this:
-(void) playPreviousSong
{
NSString *url = [[self songs] objectAtIndex:[self songIndex] - 1];
[self playSong:url];
[self setSongIndex:[self songIndex - 1];
}
This is a crude implementation just to show how it'd fit together. Basically you need to store the list of songs and keep track of which song is "selected"/playing, then just select the next/previous one.
Edit: To answer your question in the comments, you have already extracted the array of song URLs, you simply need to keep a reference to it in the class. E.g.
#interface AudioPlayer {
NSArray *_songs;
NSUInteger *_songIndex;
}
Then in the #implementation instead of creating a arrayOfSongs variable, simply reference the array from the instance variable:
_songs = [[NSArray alloc] initWithArray:[[[dict objectForKey:#"list"] objectForKey:#"songs"] objectForKey:#"song"]];
Then in, for example, the playPreviousSong method:
-(void) playPreviousSong
{
NSString *url = [_songs objectAtIndex:_songIndex - 1];
[self playSong:url];
_songIndex--;
}

Why am I getting "Message sent to deallocated instance" in Objective-C?

I have several buttons on my app that are being created dynamically. They are all pointed at the button click event when pressed. When the button pressed method is called, the sender's tag (int value) is parsed into the controller's house ID. It works with one of the buttons — the first one created, to be specific — but the others throw the following error:
-[CFNumber intValue]: message sent to deallocated instance 0xc4bb0ff0
I am not releasing these buttons anywhere in my code. I haven't set them to autorelease or anything like that. I'm just wondering why they are doing this on the click.
The button click event:
- (IBAction) ButtonClick: (id) sender
{
HouseholdViewController *controller = [[HouseholdViewController alloc] initWithNibName:#"HouseholdViewController" bundle:nil];
controller.delegate = self;
controller.HouseID = [(NSInteger)[(UIButton *)sender tag] intValue]; //this line throws an error
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
Where I am creating the buttons:
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(MyLongInScreenCoords, MyLatInScreenCoords, 50, 50);
UIImage *buttonImageNormal = [UIImage imageNamed:#"blue_pin.png"];
UIImage *strechableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:50 topCapHeight:50];
[button setBackgroundImage:strechableButtonImageNormal forState:UIControlStateNormal];
[self.view addSubview:button];
button.tag = [NSNumber numberWithInt:[[words objectAtIndex: i] intValue]];
ButtonPoints[CurrentHouseCount][0] = button;
ButtonPoints[CurrentHouseCount][1] = [NSValue valueWithCGPoint:CGPointMake(MyActualLat, MyActualLong)];
[button addTarget:self action:#selector(ButtonClick:) forControlEvents:UIControlEventTouchUpInside];
CurrentHouseCount++;
tag is an integer property, not an object. just set it
button.tag = [[words objectAtIndex: i] intValue];
and use:
controller.HouseID = [(UIButton *)sender tag];