1

我在编程方面很新,我目前正在研究我遇到一些问题的块。我很难到达在我的块中定义的对象。实际上我无法准确地解释这个问题,所以我给你一些代码和图片,并希望它是有道理的,并且你原谅我的狡猾的知识并试图帮助我理解这个问题。

所以我从运行这个块开始

- (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];
        }
    }];
}

然后调用 fetchEntries:

- (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;
    }
}

重新加载表:

- (void)refreshTableView:(NSNotification *)notif
{
    [[self tableView] reloadData];
}

这是我填充自定义表格单元格的地方:

- (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;
}

因此,当我在正常状态下穿过这些街区时,一切都像魅力一样。

但是当我从 UIActionSheet 或实际上从 UISegmentedControl(它是 UIActionSheet 的子视图)调用 fetchSite 方法时,问题就开始了,这发生在这里:

- (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)];
}

现在让我们看看 updateDeparturesFromActionSheet 方法,我们正在接近我的问题开始的地方(如果你还在阅读,谢谢你

- (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 然后最终调用 fetchEntries 方法,该方法最终填充我的表。我将收到的 obj(来自块)存储在一个名为 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;

通道对象如下所示

channel             RSSChannel *        0x07464340
NSObject                NSObject    
currentString           NSMutableString *   0x00000000
lvc                 ListViewController *    0x08c455d0
items               NSMutableArray *    0x08c452d0
sites                   NSMutableArray *    0x08c452f0
parentParserDelegate    id              0x00000000
pickerViewArray     NSMutableArray *    0x08c45320

正如您在填充表格单元格时所看到的那样,我使用来自通道对象内部项目的信息。

现在,如果到目前为止你还和我在一起(并且还没睡着),我将解释我的实际问题,现在当你(希望)拥有所有相关代码时。

因此,当我在 UIActionSheet 中按下okButton时,会调用 updateDeparturesFromActionSheet 方法。哪个调用 fetchSite 最终调用 fetchEntries 到目前为止一切都很好,这些块执行并且我得到了信息。但是当我抓取 fetchEntries obj并将其放入channel时,它似乎并没有用块obj对象抓取的新信息“更新”这个对象。其中,通道对象似乎没有在内存中获得新的位置(它保持 0x07464340)。我的第一个想法是确保频道对象被 ARC 通过删除该对象的所有所有者来释放,但似乎即使我这样做(然后用简单的 NSLog(@"%@") 再次检查它的空值,它也会不断获取它的旧值和内存引用当我触发“更新”时。

经过多次尝试释放通道对象并做各种事情(创建新数组(块外)等等)。我一直在想,我不理解的块中的一些特殊规则正在惹恼我。有任何想法吗?

如果有什么不清楚的地方请告诉我,因为我表达的很糟糕,很难解释一个你自己不理解的问题。先谢谢了。

4

0 回答 0