ios - 为什么 numberOfRowsInSections : method is invoked 5 times ? 和 numberOfSections 6 倍?

标签 ios objective-c uitableview xcode6 invoke

我再次发布这个问题,这个问题已经在这个主题中被问到了: When is tableView:numberOfRowsInSection: called in UITableView?

我正在学习 Big Nerd Ranch 类(class),似乎这个方法在我的程序中被调用了 5 次,我不明白为什么...... 它在 viewDidLoad 之后调用,甚至在初始化之后调用。但它是在调用 tableView:cellForRowAtIndexPath: 方法之前调用的。 我在代码中到处都设置了断点,NSLogs 也到处都设置了(我在代码中删除了其中一些断点以使其更清晰),但我仍然不知道每次调用之间发生了什么。

这是我的代码:

BNRAppDelegate.h

#import <UIKit/UIKit.h>

@interface BNRAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

BNRAppDelegate.m

#import "BNRAppDelegate.h"
#import "BNRItemsViewController.h"

@interface BNRAppDelegate ()

@end

@implementation BNRAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.

//Create a BNRItemsViewController
BNRItemsViewController *itemsViewController = [[BNRItemsViewController alloc] init];

//Place BNRItemsViewController's table view in the window hierarchy
self.window.rootViewController = itemsViewController;

self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
//etc...

@end

BNRItem.h

#import <Foundation/Foundation.h>

@interface BNRItem : NSObject
{
NSString *_itemName;
NSString *_serialNumber;
int _valueInDollars;
NSDate *_dateCreated;
}


@property NSString *itemName;
@property NSString *serialNumber;
@property int valueInDollars;
@property NSDate *dateCreated;

+(instancetype)randomItem;

//Designated initializer for BNRItem
-(instancetype)initWithItemName:(NSString *)name
             valueInDollars:(int)value
               serialNumber:(NSString *)sNumber;

-(instancetype)initWithItemName:(NSString *)name;


@end

BNRItem.m

#import "BNRItem.h"

@implementation BNRItem

+(instancetype)randomItem
{
//Create an immutable array of three adjectives
NSArray *randomAdjectiveList = @[@"Fluffy", @"Rusty", @"Shiny"];

//Create an immutable array of three nouns
NSArray *randomNounList = @[@"Bear", @"Spork", @"Mac"];

//Get the index of a random adjective/noun from the lists
//Note: the % operator, called the modulo operator, gives you the remainder. So adjectiveIndex is a random number from 0 to 2 inclusive.
NSInteger adjectiveIndex = arc4random() % [randomAdjectiveList count];
NSInteger nounIndex = arc4random() % [randomNounList count];

//Note the NSInteger is not an object but a type definition for "long"

NSString *randomName = [NSString stringWithFormat:@"%@ %@",
                        [randomAdjectiveList objectAtIndex:adjectiveIndex],
                        [randomNounList objectAtIndex:nounIndex]];

int randomValue = arc4random() % 100;

NSString *randomSerialNumber = [NSString stringWithFormat:@"%c%c%c%c%c",
                                '0' + arc4random() % 10,
                                'A' + arc4random() % 26,
                                '0' + arc4random() % 10,
                                'A' + arc4random() % 26,
                                '0' + arc4random() % 10];

BNRItem *newItem = [[self alloc] initWithItemName:randomName
                                   valueInDollars:randomValue
                                     serialNumber:randomSerialNumber];
return newItem;
}


-(instancetype)initWithItemName:(NSString *)name
             valueInDollars:(int)value
               serialNumber:(NSString *)sNumber
{
//Call the superclass's designated initializer
self = [super init];

//Did the superclass's designated initializer succeed?
if (self) {
    //Give the instance variables initial values
    self.itemName = name;
    self.serialNumber = sNumber;
    self.valueInDollars = value;
    //Set _dateCreated to the current date and time
    self.dateCreated = [[NSDate alloc] init];
}

//Return the address of the newly initialized object
return self;
}

-(instancetype)initWithItemName:(NSString *)name
{
return [self initWithItemName:name
               valueInDollars:0
                 serialNumber:@""];
}

-(instancetype)init
{
    return [self initWithItemName:@"Item"];
}

-(NSString *)description
{
NSString *descritptionString = [[NSString alloc] initWithFormat:@"%@ (%@): worth $%d, recorded on %@",
                                self.itemName,
                                self.serialNumber,
                                self.valueInDollars,
                                self.dateCreated];
return descritptionString;
}
@end

BNRItemStore.h

#import <Foundation/Foundation.h>

@class BNRItem;

@interface BNRItemStore : NSObject

@property (nonatomic, readonly) NSArray *allItems;

+(instancetype)sharedStore;
-(BNRItem *)createItem;

@end

BNRItemStore.m

#import "BNRItemStore.h"
#import "BNRItem.h"

@interface BNRItemStore ()

@property (nonatomic) NSMutableArray *privateItems;

@end

@implementation BNRItemStore

+(instancetype)sharedStore
{
    static BNRItemStore *sharedStore = nil;

//Do I need to create a sharedStore ?
if (!sharedStore) {
    sharedStore = [[self alloc] initPrivate];
}
return sharedStore;
}

//If a programmer calls [[BNRItemsStore alloc] init], let him know the error of his ways
-(instancetype)init
{
@throw [NSException exceptionWithName:@"Singleton"
                               reason:@"Use +[BNRItemStore sharedStore]"
                             userInfo:nil];
return nil;
}

//Here is the real (secret) intializer
-(instancetype)initPrivate
{
self = [super init];
if (self) {
    _privateItems = [[NSMutableArray alloc] init];
}
return self;
}

-(NSArray *)allItems
{
return self.privateItems;
}

-(BNRItem *)createItem
{
BNRItem *item = [BNRItem randomItem];

[self.privateItems addObject:item];

return item;
}

@end

BNRItemsViewController.h

#import <UIKit/UIKit.h>
#import "BNRItemsViewController.h"
#import "BNRItemStore.h"
#import "BNRItem.h"

@interface BNRItemsViewController : UITableViewController

@property (nonatomic) BNRItemStore *itemStore;

@end

BNRItemsViewController.m

#import "BNRItemsViewController.h"
#import "BNRItemStore.h"
#import "BNRItem.h"

@implementation BNRItemsViewController

-(BNRItemStore *)itemStore
{
BNRItemStore *itemStore = [BNRItemStore sharedStore];
return itemStore;
}

//Designated Initializer is initWithStyle  Changing to init
-(instancetype)init
{
//ALWAYS call the superclass's designated initializer
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
    for (int i = 0; i < 8; i++) {
        BNRItem *item = [self.itemStore createItem];
        NSLog(@"The %@, valued %d has been created. It is at index %lud", item.itemName, item.valueInDollars, (unsigned long)[[[BNRItemStore sharedStore] allItems] indexOfObject:item]);

    }
}
return self;

}



-(instancetype)initWithStyle:(UITableViewStyle)style
{
return [self init];
}


-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(@"This tableview has %ld section and %lu rows", (long)section, (unsigned long)[[self.itemStore allItems] count]);
return [[self.itemStore allItems] count];
}

-(UITableViewCell *)tableView:(UITableView *)tableView
    cellForRowAtIndexPath:(NSIndexPath *)indexPath
{   
//Get a new or recycled cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"  forIndexPath:indexPath];

//Set the text on the cell with the description of the item that is at the nth index of items, where n = row this cell will appear in on the tableview
NSArray *items = [self.itemStore allItems];
BNRItem *item = items[indexPath.row];
NSLog(@"%@ is in indexPath %ld - %ld", item.itemName, (long)[indexPath section], (long)[indexPath row]);


cell.textLabel.text = [item description];

return cell;
}

-(void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"ViewDidLoad1");
[self.tableView registerClass:[UITableViewCell class]
       forCellReuseIdentifier:@"UITableViewCell"];
NSLog(@"ViewDidLoad2");
}

@end

我还有另一段代码,其中有 2 个部分,因此我调用了方法 numberOfSections:,这个方法被调用了 6 次!首先连续两次,然后使用 numberOfRowsInSection 交替: 到底是什么?

最佳答案

父类(super class)(UITableView/Controller)不缓存这些值,这是一件好事:你不用告诉父类(super class),当数字发生变化时,它必须询问。这与苹果选择的白盒方法是一致的。

因此,每当苹果父类(super class)实现中的算法需要知道这些值时,它就必须调用。而且当苹果改变某些算法时,调用次数可能会发生变化。我不会想太多。没有什么问题。

唯一的结论:尽可能便宜地实现这些方法。

关于ios - 为什么 numberOfRowsInSections : method is invoked 5 times ? 和 numberOfSections 6 倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32006253/

相关文章:

ios - 在 UICollectionViewController 中使用 segue 时出错

objective-c - 将 BOOL 与 YES 进行比较是否危险?

iphone - 重新加载 TableView 数据并取消选择单元格

ios - 无论使用什么字符串,sizewithfont 始终返回相同的值

ios - AIR 移动调试 - "Enter ip address or hostname"

ios - 在两个 UiViewController 和 UIView 之间实现拖动和滑动过渡?

ios - 如何在 iOS 中构建 Cocoa touch 框架?

ios - 如何从一个 UIView 更改另一个 UIView 上的标签

objective-c - 类方法也被继承了吗?

ios - 使用 Swift 在 UITableview 中对 Backendless 数据进行分组和排序