嗨,我正在研究 Ray Wenderlich 教程,该教程在表格视图中显示购买的 IAP 列表。表格视图未排序,我希望它们按名称排序。
表格视图加载未排序的内容,没有内容,或者使用下面的代码我收到错误:
[HMContentController unlockedCycleClass]:无法识别的选择器发送到实例 0x1e56ee80 2013-06-08 11:15:47.582 GCC7.1[6659:907]由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[HMContentController unlockedCycleClass]:无法识别的选择器发送到实例 0x1e56ee80” *
这是我尝试过的代码。
HMContenController.h //模型
#import <Foundation/Foundation.h>
UIKIT_EXTERN NSString *const HMContentControllerCurrentCycleClassDidChangeNotification;
UIKIT_EXTERN NSString *const HMContentControllerUnlockedCycleClassDidChangeNotification;
@class CycleClass;
@interface HMContentController : NSObject
+ (HMContentController *)sharedInstance;
- (NSArray *) unlockedCycleClass;
- (NSArray *) sortedArray;
@property (nonatomic, strong) CycleClass * currentCycleClass;
(void)unlockCycleClassWithDirURL:(NSURL *)dirURL;
@end
HMContentController.m
#import "HMContentController.h"
#import "CycleClass.h"
NSString *const HMContentControllerCurrentCycleClassDidChangeNotification = @"HMContentControllerCurrentThemeDidChangeNotification";
NSString *const HMContentControllerUnlockedCycleClassDidChangeNotification = @"HMContentControllerUnlockedThemesDidChangeNotification";
@implementation HMContentController {
NSMutableArray * _unlockedCycleClass;
NSArray * _sortedArray; //my added code
}
+ (HMContentController *)sharedInstance {
static dispatch_once_t once;
static HMContentController * sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (id)init {
if ((self = [super init])) {
_unlockedCycleClass = [NSMutableArray array];
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];//my added sorting code
_sortedArray=[_unlockedCycleClass sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]]; //my added sorting code
BOOL hasRunBefore = [[NSUserDefaults standardUserDefaults] boolForKey:@"hasRunBefore"];
if (!hasRunBefore) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"hasRunBefore"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self setHints:20];
}
}
return self;
}
- (void)setCurrentCycleClass:(CycleClass *)currentCycleClass {
_currentCycleClass = currentCycleClass;
[[NSNotificationCenter defaultCenter] postNotificationName:HMContentControllerCurrentCycleClassDidChangeNotification object:nil];
}
- (NSArray *)unlockedCycleClass {
return _unlockedCycleClass;
}
- (void)unlockCycleClassWithDirURL:(NSURL *)dirURL {
CycleClass * cycleClass = [[CycleClass alloc] initWithDirURL:dirURL];
// Make sure we don't already have class
BOOL found = FALSE;
for (int i = 0; i < _sortedArray.count; ++i) {
CycleClass * curCycleClass = _unlockedCycleClass[i];
if ([cycleClass.name isEqualToString:curCycleClass.name]) {
NSLog(@"Cycle Class already unlocked, replacing...");
if (self.currentCycleClass == curCycleClass) {
self.currentCycleClass = cycleClass;
}
_unlockedCycleClass[i] = cycleClass;
found = TRUE;
break;
}
}
if (!found) {
// Unlock new theme
[_unlockedCycleClass addObject:cycleClass];
}
if (!self.currentTheme) {
self.currentCycleClass = cycleClass;
}
// Notify observers
[[NSNotificationCenter defaultCenter] postNotificationName:HMContentControllerUnlockedCycleClassDidChangeNotification object:self];
}
- (void)unlockContentWithDirURL:(NSURL *)dirURL {
if ([CycleClass classAtURL:dirURL]) {
[self unlockCycleClassWithDirURL:dirURL];
}
else if ([HMTheme themeAtURL:dirURL]) {
[self unlockThemeWithDirURL:dirURL];
} else if ([HMWords wordsAtURL:dirURL]) {
[self unlockWordsWithDirURL:dirURL];
} else {
NSLog(@"Unexpected content!");
}
}
@end
MyCycleClass //表格视图
#import "MyCycleClassesViewController.h"
#import "HMContentController.h"
#import "CycleClass.h"
@interface MyCycleClassesViewController () <UIActionSheetDelegate>
@property (weak, nonatomic) IBOutlet UILabel *classLabel;
@end
@implementation MyCycleClassesViewController {
NSIndexPath * _selectedIndexPath;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[self tableView] reloadData]; //refresh table
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(unlockedCycleClassChanged:) name:HMContentControllerUnlockedCycleClassDidChangeNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)unlockedCycleClassChanged:(NSNotification *)notification {
[self.tableView reloadData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [HMContentController sharedInstance].unlockedCycleClass.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
CycleClass * class = [HMContentController sharedInstance].sortedArray[indexPath.row]; //originally sortedArray was .unlockedCycleClass which loaded unordered classes
if ([HMContentController sharedInstance].currentCycleClass == class) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
_selectedIndexPath = indexPath;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
cell.textLabel.text = class.name;
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSMutableArray * indexPathsToReload = [NSMutableArray array];
if (_selectedIndexPath) {
[indexPathsToReload addObject:_selectedIndexPath];
}
if (![indexPath isEqual:_selectedIndexPath]) {
[indexPathsToReload addObject:indexPath];
}
CycleClass * class = [HMContentController sharedInstance].sortedArray[indexPath.row];
[[HMContentController sharedInstance] setCurrentCycleClass:class];
[self.tableView reloadRowsAtIndexPaths:indexPathsToReload withRowAnimation:UITableViewRowAnimationNone];
}
@结尾
CycleClass.h/m(以防万一它有帮助,IAP 信息)
#import <Foundation/Foundation.h>
@interface CycleClass : NSObject
@property (nonatomic, readonly, strong) NSURL * dirURL;
@property (nonatomic, readonly, strong) NSString * name;
@property (nonatomic, readonly, strong) NSURL * noMusicURL;
@property (nonatomic, readonly, strong) NSURL * withMusicURL;
@property (nonatomic, readonly, strong) NSURL * imageURL;
+ (BOOL)classAtURL:(NSURL *)url;
- (id)initWithDirURL:(NSURL *)url;
@end
import "CycleClass.h"
@implementation CycleClass
+ (BOOL)classAtURL:(NSURL *)url {
NSURL * plistURL = [url URLByAppendingPathComponent:@"cycleClass.plist"];
return [[NSFileManager defaultManager] fileExistsAtPath:plistURL.path];
}
- (id)initWithDirURL:(NSURL *)url {
if ((self = [super init])) {
_dirURL = url;
NSURL * plistURL = [url URLByAppendingPathComponent:@"cycleClass.plist"];
NSDictionary * dict = [NSDictionary dictionaryWithContentsOfURL:plistURL];
if (dict == nil) return nil;
_name = dict[@"name"];
NSString * noMusicString = dict[@"noMusic"];
if (noMusicString) {
_noMusicURL = [url URLByAppendingPathComponent:noMusicString];
}
NSString * withMusicString = dict[@"withMusic"];
if (withMusicString) {
_withMusicURL = [url URLByAppendingPathComponent:withMusicString];
}
NSString * imageString = dict[@"image"];
if (imageString) {
_imageURL = [url URLByAppendingPathComponent:imageString];
}
}
return self;
}
@end
和 IAP plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>name</key>
<string>2. Simon Beginner Hills</string>
<key>noMusic</key>
<string>simon2NoMusic.mp3</string>
<key>withMusic</key>
<string>simon2Music.mp3</string>
<key>image</key>
<string>simongraph2.png</string>
</dict>
</plist>
我对此完全感到困惑,但似乎应该有一个简单明显的解决方法......请帮忙!