我再次发布这个问题,这个问题已经在这个主题中被问到了: 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/