0

使用 plist 并尝试返回数据时,我有这种奇怪的行为。为了给你一个概述,plist 在每个对象中有 12 个条目,所以我希望有 12 个,但我得到 13 个,第一个结果为,而其余 12 个实际上是正确的。

这是我的 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>
    <array>
        <string>Audit</string>
        <string>Tax</string>
        <string>Digital</string>
        <string>Consulting</string>
        <string>Risk Advisory</string>
        <string>Finance</string>
        <string>Audit</string>
        <string>Tax</string>
        <string>Digital</string>
        <string>Consulting</string>
        <string>Advisory</string>
        <string>Finance</string>
    </array>
    <key>Logo</key>
    <array>
        <string>page.png</string>
        <string>page.png</string>
        <string>page.png</string>
        <string>page.png</string>
        <string>page.png</string>
        <string>page.png</string>
        <string>page.png</string>
        <string>page.png</string>
        <string>page.png</string>
        <string>page.png</string>
        <string>page.png</string>
        <string>page.png</string>
    </array>
</dict>
</plist>

这是我的 ViewController.h 文件:

#import <UIKit/UIKit.h>
#import "iCarousel.h"


@interface PackViewController : UIViewController <iCarouselDataSource, iCarouselDelegate>
{
    NSMutableArray      *packName;
    NSMutableArray      *packLogo;
}

@property (nonatomic, retain) IBOutlet iCarousel *carousel;
@property (nonatomic, retain) NSMutableArray  *packName;
@property (nonatomic, retain) NSMutableArray  *packLogo;

@end

然后,这是我的 ViewController.m 文件:

#import "PackViewController.h"
#import "AsyncImageView.h"


@interface PackViewController () <UIActionSheetDelegate>

@property (nonatomic, assign) BOOL wrap;
@property (nonatomic, retain) NSMutableArray *items;

@end


@implementation PackViewController

@synthesize carousel, wrap, items;
@synthesize packName, packLogo;

- (void)awakeFromNib
{
    //set up data
    wrap = YES;

    NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"Pack" ofType:@"plist"];
    NSArray *plistItems = [NSDictionary dictionaryWithContentsOfFile:plistPath];
    NSArray *plistData = [plistItems valueForKey:@"Name"];

    self.items = [NSMutableArray array];
    for (int i = 0; i < [plistData count]; i++)
    {
        [items addObject:[NSNumber numberWithInt:i]];
        NSLog(@"First Index Name %@",[items objectAtIndex:i]);
    }
}

- (void)dealloc
{
    carousel.delegate = nil;
    carousel.dataSource = nil;

    [carousel release];
    [super dealloc];
}

#pragma mark -
#pragma mark View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Pack.plist code
    // get paths from root direcory
    NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
    // get documents path
    NSString *documentsPath = [paths objectAtIndex:0];
    // get the path to our Pack.plist file
    NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"Pack.plist"];

    // check to see if Pack.plist exists in documents
    if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
    {
        // if not in documents, get property list from main bundle
        plistPath = [[NSBundle mainBundle] pathForResource:@"Pack" ofType:@"plist"];
    }

    // read property list into memory as an NSData object
    NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
    NSString *errorDesc = nil;
    NSPropertyListFormat format;
    // convert static property list into dictionary object
    NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization
                                          propertyListFromData:plistXML
                                          mutabilityOption:NSPropertyListMutableContainersAndLeaves
                                          format:&format
                                          errorDescription:&errorDesc];
    if (!temp)
    {
        NSLog(@"Error reading plist: %@, format: %d", errorDesc, format);
    }
    // assign values
    self.packName = [NSMutableArray arrayWithArray:[temp objectForKey:@"Name"]];
    self.packLogo = [NSMutableArray arrayWithArray:[temp objectForKey:@"Logo"]];

    // configure carousel
    carousel.type = iCarouselTypeInvertedWheel;
    carousel.vertical = true;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    self.carousel = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

#pragma mark -
#pragma mark UIActionSheet methods

- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    if (buttonIndex >= 0)
    {
        //map button index to carousel type
        iCarouselType type = buttonIndex;

        //carousel can smoothly animate between types
        [UIView beginAnimations:nil context:nil];
        carousel.type = type;
        [UIView commitAnimations];
    }
}

#pragma mark -
#pragma mark iCarousel methods

- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel
{
    //NSLog(@"numberOfItemsInCarousel count: %i", [items count]);
    return [items count];
}

- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
    UIButton *button = (UIButton *)view;
    UILabel *label = nil;

    if (button == nil)
    {
        //no button available to recycle, so create new one
        UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"%@", [packLogo objectAtIndex:index]]];
        //NSLog(@"companyLogo: %@", [packLogo objectAtIndex:index]);
        button = [UIButton buttonWithType:UIButtonTypeCustom];
        button.frame = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height);
        [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [button setBackgroundImage:image forState:UIControlStateNormal];
        button.titleLabel.font = [button.titleLabel.font fontWithSize:20];
        [button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];

        label = [[[UILabel alloc] initWithFrame:view.bounds] autorelease];
        label.backgroundColor = [UIColor clearColor];
        label.textAlignment = UITextAlignmentCenter;
    }
    else
    {
        //get a reference to the label in the recycled view
        label = (UILabel *)[view viewWithTag:1];
    }
    //set button label
    [button setTitle:[self.packName objectAtIndex:index] forState:UIControlStateNormal];
    NSLog(@"companyName: %@", [items objectAtIndex:index]);

    return button;
}

#pragma mark -
#pragma mark item tap event

- (void)buttonTapped:(UIButton *)sender
{
    //get item index for button
    NSInteger index = [carousel indexOfItemViewOrSubview:sender];

    [[[[UIAlertView alloc] initWithTitle:@"Button Tapped"
                                 message:[NSString stringWithFormat:@"You tapped button number %i", index]
                                delegate:nil
                       cancelButtonTitle:@"OK"
                       otherButtonTitles:nil] autorelease] show];
}

- (CATransform3D)carousel:(iCarousel *)_carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform
{
    CGFloat count = _carousel.numberOfVisibleItems;
    CGFloat spacing = 1.0f;
    CGFloat arc = M_PI * 2.0f;
    CGFloat radius = _carousel.itemWidth * spacing * count / arc;
    CGFloat angle = arc / count * offset;

    return CATransform3DTranslate(transform, radius - radius * cos(angle), radius * sin(angle), 0.0f);
}

- (CGFloat)carousel:(iCarousel *)_carousel valueForOption:(iCarouselOption)option withDefault:(CGFloat)value
{
    //customise carousel display
    switch (option)
    {
        case iCarouselOptionWrap:
        {
            //normally you would hard-code this to YES or NO
            return wrap;
        }
        case iCarouselOptionSpacing:
        {
            //add a bit of spacing between the item views
            return value * 1.05f;
        }
        case iCarouselOptionFadeMax:
        {
            if (carousel.type == iCarouselTypeCustom)
            {
                //set opacity based on distance from camera
                return 0.0f;
            }
            return value;
        }
        default:
        {
            return value;
        }
    }
}

@end

你可以看到我的 M 文件中有两行代码输出两个 NSLog 项。这些是:

NSLog(@"First Index Name %@",[items objectAtIndex:i]);
NSLog(@"companyName: %@", [items objectAtIndex:index]);

awakeFromNib 的 for 循环中包含的“第一个索引名称”的输出是:

2013-05-21 22:43:23.875 Pack[7496:c07] First Index Name 0
2013-05-21 22:43:23.877 Pack[7496:c07] First Index Name 1
2013-05-21 22:43:23.878 Pack[7496:c07] First Index Name 2
2013-05-21 22:43:23.879 Pack[7496:c07] First Index Name 3
2013-05-21 22:43:23.880 Pack[7496:c07] First Index Name 4
2013-05-21 22:43:23.880 Pack[7496:c07] First Index Name 5
2013-05-21 22:43:23.881 Pack[7496:c07] First Index Name 6
2013-05-21 22:43:23.881 Pack[7496:c07] First Index Name 7
2013-05-21 22:43:23.882 Pack[7496:c07] First Index Name 8
2013-05-21 22:43:23.882 Pack[7496:c07] First Index Name 9
2013-05-21 22:43:23.883 Pack[7496:c07] First Index Name 10
2013-05-21 22:43:23.883 Pack[7496:c07] First Index Name 11

如您所见,我以正确的顺序获得了所有 12 个值,这是我对第二个值的期望,但这就是问题所在。对于包含在-(UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view我输出items数组中的第二个 NSLog只是想看看发生了什么。这就是我所看到的:

2013-05-21 22:43:23.916 Pack[7496:c07] companyName: 0
2013-05-21 22:43:23.918 Pack[7496:c07] companyName: 0
2013-05-21 22:43:23.919 Pack[7496:c07] companyName: 11
2013-05-21 22:43:23.920 Pack[7496:c07] companyName: 7
2013-05-21 22:43:23.921 Pack[7496:c07] companyName: 6
2013-05-21 22:43:23.922 Pack[7496:c07] companyName: 2
2013-05-21 22:43:23.922 Pack[7496:c07] companyName: 1
2013-05-21 22:43:23.923 Pack[7496:c07] companyName: 10
2013-05-21 22:43:23.924 Pack[7496:c07] companyName: 9
2013-05-21 22:43:23.925 Pack[7496:c07] companyName: 8
2013-05-21 22:43:23.925 Pack[7496:c07] companyName: 5
2013-05-21 22:43:23.926 Pack[7496:c07] companyName: 4
2013-05-21 22:43:23.927 Pack[7496:c07] companyName: 3

同样,前两个结果都是两者0,并且与第一次迭代不同,排序非常混乱。我在 SO 上发现了一个线程,其中提到 plist 不一定按顺序输出,因为它们只是关键对象,所以我明白了,但核心问题是前两个结果。

如果我更改我的 NSLog 以输出self.packName(如下所示:)的结果,NSLog(@"companyName: %@", [self.packName objectAtIndex:index]);则返回以下内容:

2013-05-21 22:49:43.663 Pack[7543:c07] companyName: (null)
2013-05-21 22:49:43.665 Pack[7543:c07] companyName: Audit
2013-05-21 22:49:43.666 Pack[7543:c07] companyName: Finance
2013-05-21 22:49:43.667 Pack[7543:c07] companyName: Tax
2013-05-21 22:49:43.668 Pack[7543:c07] companyName: Audit
2013-05-21 22:49:43.669 Pack[7543:c07] companyName: Digital
2013-05-21 22:49:43.669 Pack[7543:c07] companyName: Tax
2013-05-21 22:49:43.670 Pack[7543:c07] companyName: Risk Advisory
2013-05-21 22:49:43.671 Pack[7543:c07] companyName: Consulting
2013-05-21 22:49:43.672 Pack[7543:c07] companyName: Digital
2013-05-21 22:49:43.672 Pack[7543:c07] companyName: Finance
2013-05-21 22:49:43.673 Pack[7543:c07] companyName: Risk Advisory
2013-05-21 22:49:43.673 Pack[7543:c07] companyName: Consulting

正如您再次看到的那样,第一个结果是(null),我很难理解为什么会发生这种情况。

为了进一步调试,我运行了这个 NSLog:NSLog(@"companyName: %@", packName);以将原始结果作为数组输出,结果如下:

2013-05-21 22:52:59.284 Pack[7581:c07] companyName: (
    "Audit",
    "Tax",
    "Digital",
    "Consulting",
    "Risk Advisory",
    "Finance",
    "Audit",
    "Tax",
    "Digital",
    "Consulting",
    "Advisory",
    "Finance"
)

数组中没有(null)结果,所以我不知道这个流氓空值来自哪里。

任何帮助将不胜感激!!!!

4

1 回答 1

3

对于包含在中的第二个 NSLog,carousel:viewForItemAtIndex:reusingView:我输出 items 数组只是为了看看发生了什么。

不,您输出的只是一个元素items:在 iCarousel 委托回调中传递索引的元素。您无法控制 iCarousel 何时发送此消息并且未指定索引的顺序。这解释了以下输出

2013-05-21 22:43:23.916 Pack[7496:c07] companyName: 0
2013-05-21 22:43:23.918 Pack[7496:c07] companyName: 0
2013-05-21 22:43:23.919 Pack[7496:c07] companyName: 11
...

同样,前两个结果都是 0,并且与第一次迭代不同,排序非常混乱。我在 SO 上发现了一个线程,其中提到 plist 不一定按顺序输出,因为它们只是关键对象,所以我明白了,但核心问题是前两个结果。

如前所述,顺序取决于 iCarousel 实现。它与 plist 无关。您误读了链接的帖子,它可能与字典中的顺序有关。当然,plist 会保留数组元素的顺序。

如果我更改我的 NSLog 以输出 self.packName 的结果(如下所示:NSLog(@"companyName: %@", [self.packName objectAtIndex:index]);) 这里是返回的内容:

2013-05-21 22:49:43.663 Pack[7543:c07] companyName: (null)
2013-05-21 22:49:43.665 Pack[7543:c07] companyName: Audit
...

带有 (null) 结果的行只能表示一件事:在第一次回调时,itemsivar 尚未初始化。objectAtIndex:永远不能回来nil,所以这是唯一的解释。您可以使用调试器检查,在回调中设置断点和awakeFromNib.

于 2013-05-21T21:19:42.917 回答