Im pretty new in programming and im currently looking at blocks which im having some issues with. Im having a hard time reaching an object which is defined within my block. Actually I cannot really explain this issue in an accurate way, so ill give you some code and pictures, and hope that it makes sense and that you excuse my dodgy knowledge and try to help me understand the problem.
So Im starting off by running this block
- (void)fetchSite
{
//Initiate the request...
[[FeedStore sharedStore] fetchSites:^(RSSChannel *objSite, NSError *err) {
//When the request completes, this block will be called
if (!err) {
//If everything went ok, grab the object
channelSite = objSite;
//Now we need to extract the first siteId and give it to sharedstore
RSSItem *site = [[channelSite sites] objectAtIndex:0];
NSString *currentSiteId = [NSString stringWithFormat:@"%@", [site siteNumber]];
NSLog(@"DEBUG: LVC: fetchSite: currentSiteId: %@", currentSiteId);
[[FeedStore sharedStore] setCurrentSiteId:currentSiteId];
//Now we can call fetchEntries
[self fetchEntries];
} else {
//If things went bad, show an alart view
UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Fel" message:@"Kunde inte bedömma din position relaterat till närmaste hållplats, försök gärna igen" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[av show];
//Stop UIRefreshControl
[refreshControl endRefreshing];
}
}];
}
Then fetchEntries is called:
- (void)fetchEntries
{
void (^completionBlock)(RSSChannel *obj, NSError *err) = ^(RSSChannel *obj, NSError *err) {
if (!err) {
//If everything went ok, grab the object, and reload the table and end refreshControl
channel = obj;
//Post notification to refreshTableView method which will reload tableViews data.
[[NSNotificationCenter defaultCenter] postNotificationName:@"RefreshTableView" object:nil];
//Stop UIRefreshControl
[refreshControl endRefreshing];
} else {
//If things went bad, show an alart view
UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Fel" message:@"Kunde inte hämta avgångar för din hållplats, försök gärna igen" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[av show];
//Stop UIRefreshControl
[refreshControl endRefreshing];
}
};
//Initiate the request...
if (fetchType == ListViewControllerFetchBus) {
[[FeedStore sharedStore] fetchDepartures:completionBlock];
selectedSegment = 0;
} else {
[[FeedStore sharedStore] fetchDeparturesMetro:completionBlock];
selectedSegment = 1;
}
}
Reloading the table:
- (void)refreshTableView:(NSNotification *)notif
{
[[self tableView] reloadData];
}
Heres where I populate my custom table cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Get received data from fetchEntries block
RSSItem *item = [[channel items] objectAtIndex:[indexPath row]];
//Get the new or recycled cell
ItemCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ItemCell"];
//Set the apperance
[[cell lineNumberLabel] setTextColor:[UIColor whiteColor]];
[[cell lineNumberLabel] minimumScaleFactor];
[[cell lineNumberLabel] setFont:[UIFont boldSystemFontOfSize:22]];
[[cell lineNumberLabel] adjustsFontSizeToFitWidth];
[[cell lineNumberLabel] setTextAlignment:NSTextAlignmentCenter];
[[cell destinationLabel] setTextColor:[UIColor whiteColor]];
[[cell displayTimeLabel] setTextColor:[UIColor whiteColor]];
[[cell displayTimeLabel] setTextAlignment:NSTextAlignmentLeft];
//Configure the cell with the item
if ([item lineNumber]) [[cell lineNumberLabel] setText:[item lineNumber]];
if ([item destination]) [[cell destinationLabel] setText:[item destination]];
if ([item displayTime]) [[cell displayTimeLabel] setText:[item displayTime]];
if ([item displayRow1]) [[cell destinationLabel] setText:[item displayRow1]];
return cell;
}
So when im running through these blocks in normal state everything works like a charm.
But the issues starts when Im calling fetchSite method from an UIActionSheet, or actually from an UISegmentedControl which is a subview of UIActionSheet, this takes place here:
- (void)displayPickerView
{
//First im creating an instance to PickerViewController which will handle the UIPickerView which is a subview of UIActionSheet. pickerArrayFromChannel holds entries for UIPickerView to show in its ViewController.
pickerViewController = [[PickerViewController alloc] init];
[pickerViewController initWithItems: pickerArrayFromChannel];
pickerViewController.delegate = self;
//initiate UIActionSheet which needs no delegate or appearance more than its style
actionSheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:nil
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
//Create frame and initiate a UIPickerView with this. Set its delegate to the PickerViewController and set it to start at row 0
CGRect pickerFrame = CGRectMake(0, 40, 0, 0);
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerView.showsSelectionIndicator = YES;
pickerView.delegate = pickerViewController;
pickerView.dataSource = pickerViewController;
[pickerView selectRow:0 inComponent:0 animated:YES];
//Add this pickerView as subview to actionSheet
[actionSheet addSubview:pickerView];
//Now, create two buttons, closeButton and okButton. Which really are UISegmentedControls. Action to closeButton is (for now) dismissActionSheet which holds only following code " [actionSheet dismissWithClickedButtonIndex:0 animated:YES]; " and works fine
UISegmentedControl *closeButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:@"Stäng"]];
closeButton.momentary = YES;
closeButton.frame = CGRectMake(260, 7.0f, 50.0f, 30.0f);
closeButton.segmentedControlStyle = UISegmentedControlStyleBar;
closeButton.tintColor = [UIColor blackColor];
[closeButton addTarget:self action:@selector(dismissActionSheet) forControlEvents:UIControlEventValueChanged];
[actionSheet addSubview:closeButton];
//OK button
UISegmentedControl *okButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:@"Visa avgångar"]];
okButton.momentary = YES;
okButton.frame = CGRectMake(10, 7.0f, 100.0f, 30.0f);
okButton.segmentedControlStyle = UISegmentedControlStyleBar;
okButton.tintColor = [UIColor blueColor];
[okButton addTarget:self action:@selector(updateDeparturesFromActionSheet) forControlEvents:UIControlEventValueChanged];
[actionSheet addSubview:okButton];
//Now show actionSheet
[actionSheet showInView:[[UIApplication sharedApplication] keyWindow]];
[actionSheet setBounds:CGRectMake(0, 0, 320, 485)];
}
Now lets look at updateDeparturesFromActionSheet method and we're getting close to where my issues begin (if your still reading, thank you for that
- (void)updateDeparturesFromActionSheet
{
//Dismiss the actionSheet
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
//Send the selected entry from UIPickerView to currentAddress property in FeedStore, fetchSite method will eventually use this
[[FeedStore sharedStore] setCurrentAddress:[pickerViewController addressFromPickerView]];
//Call fetchSite method
[self fetchSite];
}
fetchSite then eventually calls fetchEntries method, which eventually populate my table. I store received obj (from block) in an property called channel
void (^completionBlock)(RSSChannel *obj, NSError *err) = ^(RSSChannel *obj, NSError *err) {
if (!err) {
//If everything went ok, grab the object, and reload the table and end refreshControl
channel = obj;
The channel object looks like this
channel RSSChannel * 0x07464340
NSObject NSObject
currentString NSMutableString * 0x00000000
lvc ListViewController * 0x08c455d0
items NSMutableArray * 0x08c452d0
sites NSMutableArray * 0x08c452f0
parentParserDelegate id 0x00000000
pickerViewArray NSMutableArray * 0x08c45320
As you can see when I populate my tables cells, I use the info from items inside of the channel object.
Now if your still with me (and havnt fallen asleep) so far I will explain my actual problem, now when you have (hopefully) all the relevant code.
So when I press okButton in my UIActionSheet, updateDeparturesFromActionSheet method gets called. Which calls fetchSite which eventually calls fetchEntries and so far so good, these blocks performs and I get back information. But when I grab fetchEntries obj and put it in channel, it doesnt seems to "update" this object with the new information grabbed by the blocks obj object. Among others it does not seems that channel object gets a new place in the memory (it keeps 0x07464340). My first thought was to make sure channel object gets released by ARC, by removing all owners of that object, but it seems that even if I do so (and then doublecheck that its null with simple NSLog(@"%@") it keeps getting its old values and memory reference back when I trigger the "update".
After many attempts to release the channel object and doing all sorts of stuff (creating new arrays (outside of block) amongst other things). I keep thinking that some special rule within blocks that I dont understand is messing with me. Any ideas?
Please let me know if anything isnt clear because I've expressed myself bad, its hard to explain an issue that you dont understand yourself. Thanks in advanced.