Obj-C:来自块的对象问题

时间:2013-04-30 18:36:35

标签: ios objective-c block objective-c-blocks

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

所以我开始运行这个块

- (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调用fetchSite方法开始,或实际上是从UIAegmentedControl(UIActionSheet的子视图)调用时,会发生在这里:

- (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方法。哪个调用最终调用fetchEntries的fetchSite,到目前为止一直很好,这些块执行并返回信息。但是当我抓住fetchEntries obj 并将其放入频道时,它似乎并没有“更新”此对象,而是使用块 obj 对象。其中似乎 channel 对象在内存中获得一个新位置(它保持0x07464340)。 我的第一个想法是确保ARC释放通道对象,删除该对象的所有所有者,但似乎即使我这样做(然后用简单的NSLog(@@)再次检查它的null。 “%@”)当我触发“更新”时,它会继续获取旧值和内存引用。

经过多次尝试发布频道对象并做各种事情(创建新数组(在块之外)等)。我一直在想,我不理解的一些特殊规则是在弄乱我。有什么想法吗?

如果有什么不清楚,请告诉我,因为我表达了自己的不好,很难解释一个你不了解自己的问题。谢谢你提前。

0 个答案:

没有答案