开发者

XCode inconsistent results across several computers

So a project group member and I have been working on our parts separately. I've been working on half of the views in the app and he has worked on the other half. I sent him my half to combine with his half, but when he tried to open my half and run it, we got inconsistent results. We have not combined them yet, so they shouldn't be acting differently. I tried to test it on several other computers and they all gave the same result (different from mine).

The following code is supposed to print "CHECKED X". X represents the number of cells that are ticked at that point. On my computer, it prints "CHECKED 1..2..3..4" and you can only select up to 4, depending on how many are ticked. On any other computer it prints "CHECKED 0" and you can tick as many as you like (but you can't untick them). The code for ticking them is here:

- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

        UITableViewCell *cell = [tableView cellForRowAtIndexPath: indexPath];
        [tableView deselectRowAtIndexPath:indexPath animated:YES];

        if ((cell.accessoryType == UITableViewCellAccessoryNone) && [[DataContainerSingleton theDataContainerSingleton].favourites count] < 4 && ![self.tickedIndexPaths containsObject:indexPath])
        {
                cell.accessoryType = UITableViewCellAccessoryCheckmark;
                [self.tickedIndexPaths addObject:indexPath];

                [[DataContainerSingleton theDataContainerSingleton].favourites addObject:[drinks objectAtIndex:indexPath.row]]; // DOES NOT ADD AN OBJECT?
                NSLog(@"CHECKED %d", [[DataContainerSingleton theDataContainerSingleton].favourites count]);
        }
        else if (cell.accessoryType == UITableViewCellAccessoryCheckmark)
        {
     开发者_运维问答       [self.tickedIndexPaths removeObject:indexPath];
            for (int i = 0; i < [[DataContainerSingleton theDataContainerSingleton].favourites count]; i++)
            {
                NSString *drinkName = [[drinks objectAtIndex:indexPath.row] name];
                NSString *favName = [[[DataContainerSingleton theDataContainerSingleton].favourites objectAtIndex:i] name];

                if ([drinkName isEqualToString: favName])
                {
                    cell.accessoryType = UITableViewCellAccessoryNone;
                    [[DataContainerSingleton theDataContainerSingleton].favourites removeObjectAtIndex:i];
                    NSLog(@"UNCHECKED %d", [[DataContainerSingleton theDataContainerSingleton].favourites count]);
                }
            }

        }

}

It seems to me like the favourites array in my data container singleton is not being filled. The drinks array is not empty.

Here is the code for the DataContainerSingleton class:

DataContainerSingleton.h

#import <Foundation/Foundation.h>


@interface DataContainerSingleton : NSObject 
{
    NSMutableArray *favourites;
    NSMutableArray *drinks;
    NSString *name;
    int caffeine;

    @private

}

@property (nonatomic, retain) NSMutableArray *favourites;
@property (nonatomic, retain) NSMutableArray *drinks;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, assign) int caffeine;

+ (DataContainerSingleton *) theDataContainerSingleton;
@end

DataContainerSingleton.m

#import "DataContainerSingleton.h"


@implementation DataContainerSingleton

@synthesize favourites, drinks;
@synthesize name, caffeine;

static DataContainerSingleton* _theDataContainerSingleton = nil;

+ (DataContainerSingleton*) theDataContainerSingleton;
{
    if (!_theDataContainerSingleton)
        _theDataContainerSingleton = [[DataContainerSingleton alloc] init];
    return _theDataContainerSingleton;
}

- (id)init
{
    self = [super init];
    if (self) 
    {
        self.favourites = [[[NSMutableArray alloc] init] autorelease];
    }

    return self;
}

- (void)dealloc
{
    [super dealloc];
}

@end

I've checked all the dependencies in the program, none of them are outside the folder that I copy over. I've cleaned and cleaned the build folder but it still prints 0.

Does anybody have any idea what could be causing this inconsistency? Thanks in advance.


I sent him my half to combine with his half

Start using version control software. You are making things needlessly difficult for yourself. There is a small learning curve at first, but it pays off even on your first non-trivial project.

If you are sure that you have identical copies of the codebase, then you can probably narrow it down to one of the following:

  • Different toolchain. Make sure you are both running the same version of Xcode with the same versions of all the SDKs etc.

  • Different data. Delete the app from your devices and try again.

  • Lingering files in the bundle. Installing a development version via Xcode doesn't remove old files from the bundle. You might have files in your bundle that he does not or vice-versa. Delete the app from your devices and try again.

  • Different hardware. Occasionally bugs manifest themselves only on certain hardware. Different device capabilities can send the same code down different paths. Both of you try testing in the simulator temporarily.


I think the "inconsistent results" you mention could be due to the fact that you may have made a connection in Interface Builder for the delegate and dataSource of your tableView to the DataContainerSingleton, but your friend has a different version of the .xib in which that connection is not present. That would not give any compile errors or warnings, but would present itself as a "bug" where none of the delegate or datasource methods are actually called. Since you can see the logging statements, I would presume the delegate is set properly but the dataSource is not..?

The other option is that your cellForRowAtIndexPath method is returning a new cell each time (without a checkmark, hence you can only check but never uncheck).

EDIT: To be more precise about this, you should have code in cellForRowAtIndexPath along these lines:

UITableViewCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:@"drinkCell"];
if(cell == nil) // we need to create a new one
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
            reuseIdentifier:@"drinkCell"];
}

if([tickedIndexPaths containsObject:indexPath])
{
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
    cell.accessoryType = UITableViewCellAccessoryNone;
}

Otherwise, if the iPhone is low on memory, the OS will ask the application to purge any not strictly necessary objects from memory, which includes your existing cells. So the next time you go to retrieve the cell at row 2, for example, it'll have to create a new UITableViewCell object with default values, which means an accessory of None. Due to this, you should explicitly set the checkmark every time you get the cell.

After seeing your first comment: Okay. You should ensure you don't add a duplicate indexPath. If a row is selected, make sure that checkedIndexPaths doesn't contain the path you're about to add.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜