无法排序UITableView的内容

时间:2013-06-08 16:44:04

标签: ios uitableview sorting nssortdescriptor

您好我正在使用Ray Wenderlich教程,该教程在tableview中显示已购买的IAP列表。表视图没有排序,我希望它们按名称排序。

tableview加载未分类的内容,没有内容,或者下面的代码我得到错误:

[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 // tableview

#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];

}

@end

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>

我对此完全感到困惑,但似乎应该有一个简单的明显修复......请帮助!!

1 个答案:

答案 0 :(得分:0)

正如rdelmar所说,你需要在填充数组后进行排序。

每当unlockedCycleClass(顺便说一下是一个数组,而不是一个类)被更新时,你想确保sortedArray得到更新。因此,例如在HMContentController.m中,您可以重复您的行:

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];//my added sorting code
_sortedArray=[_unlockedCycleClass sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]]; //my added sorting code

在unlockCycleClassWithDirURL函数内部

之后
[_unlockedCycleClass addObject:cycleClass];

这不是最有效的做事方式,但我认为应该有效。