方法之间的范围

时间:2016-01-01 00:00:03

标签: objective-c scope

另一个新手问题。我试图了解如何有效地使用范围来组织我的项目使用类来保存数据而不是在视图控制器上拥有所有内容。所以,我正在研究一个简单项目的几个版本,以了解范围的工作原理。 我有一个视图控制器挂钩到视图。在该视图中,有一些按钮在单击时显示图像。我想添加另一个随机化图像的按钮。我还有一个名为“卡片”的班级来举行卡片以及创建和改组卡片的方法。我复制了这个项目,所以我有一个有效,有一个没有。

第一个项目。这些是文件:

查看控制器h文件:

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

@interface ViewController : UIViewController

- (IBAction)buttonPressed:(id)sender;

@end

查看控制器m文件:

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    Cards *instance = [[Cards alloc] init];

    instance.images = [instance createImages];

    NSLog(@"I've got %lu Images", (unsigned long)instance.images.count);

    instance.shuffled = [instance shuffleImages];

    NSLog(@"Image numbers shuffled: %@", instance.shuffled);
  }

- (IBAction)buttonPressed:(id)sender {

   //Nothing hooked to this yet

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

卡片h文件:

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

@interface Cards : NSObject

// Creating Images

@property NSMutableArray *images;

- (NSMutableArray*) createImages;

//Shuffling Images

@property NSMutableArray *shuffled;

- (NSMutableArray*) shuffleImages;

@end

卡片m文件:

#import "Cards.h"

@implementation Cards

- (NSMutableArray*) createImages{
    self.images = [[NSMutableArray alloc] initWithObjects:

                   [UIImage imageNamed:@"Image1.png"],
                   [UIImage imageNamed:@"Image2.png"],
                   [UIImage imageNamed:@"Image3.png"],
                   [UIImage imageNamed:@"Image4.png"], nil];

    return self.images;
}

- (NSMutableArray*) shuffleImages{

    NSUInteger imageCount = [self.images count];

    NSMutableArray *localvar = [[NSMutableArray alloc]init];

    for (int tileID = 0; tileID < imageCount; tileID++){
        [localvar addObject:[NSNumber
                             numberWithInt:tileID]];
    }

    for (NSUInteger i = 0; i < imageCount; ++i) {
            NSInteger nElements = imageCount - i;
            NSInteger n = (arc4random() % nElements) + i;
            [localvar exchangeObjectAtIndex:i
                                    withObjectAtIndex:n];
    }

    return localvar;
}

@end

这样可以在控制台上获得预期的输出:

2015-12-31 23:43:44.885 VCScope[2138:533369] I've got 4 Images
2015-12-31 23:43:44.886 VCScope[2138:533369] Image numbers shuffled: (
    0,
    2,
    3,
    1
)

第二个项目:

我想要做的是,只有按下按钮时才会按下按钮来随机化图像,而不是作为viewDidLoad的一部分。因此,在我的第二个项目中,我有视图controller.h和Cards.h和Cards.m的相同文件,但是在视图controller.m上我移动调用方法来调整卡片。到UIButton方法,如下:

新的View控制器m文件:

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    Cards *instance = [[Cards alloc] init];

    instance.images = [instance createImages];

    NSLog(@"I've got %lu Images", (unsigned long)instance.images.count);

  }

- (IBAction)buttonPressed:(id)sender {

    Cards *instance = [[Cards alloc] init];

    instance.shuffled = [instance shuffleImages];

    NSLog(@"Image numbers shuffled: %@", instance.shuffled);

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

这将向控制台输出以下内容:

2015-12-31 23:32:07.495 4StackVCScope[2029:486608] I've got 4 Images
2015-12-31 23:32:11.924 4StackVCScope[2029:486608] Image numbers: (
)

所以它不起作用,我猜它与范围有关。有人会对此有所启发吗?感谢

1 个答案:

答案 0 :(得分:1)

欢迎使用Stack Overflow。你提到你是一个&#34;新手&#34;,但知道你有什么背景会很有帮助,所以我知道这里需要多少细节。

Cards *instance = [[Cards alloc] init];

在局部变量中创建一个新的Cards实例。您是在-viewDidLoad-buttonPressed:内单独执行此操作。

如果每个ViewController需要一个Cards对象,那么视图控制器需要为其提供每个实例的存储空间。有几种可能的方法可以做到这一点。您选择哪一个是代码风格和API设计的问题。

如果Cards实例仅供内部使用,您可以在@implementation块中声明一个ivar:

@implementation ViewController {
    Cards *_cards;
}

- (void)viewDidLoad { _cards = ... }

- (IBAction)buttonPressed:(id)sender { access _cards }

@end

(Ivars也可以在公开@interface中声明,但我不建议这样做,因为它泄漏了实施细节。)

或者您可以在公共界面中使用属性:

// in your .h file:
@interface ViewController
@property (nonatomic) Cards *cards;
@end

// in your @implementation:
- (void)viewDidLoad { self.cards = ... }

- (IBAction)buttonPressed:(id)sender { access self.cards }

属性也可以在class extension中私下声明:

// in your .m file:
@interface ViewController ()
@property (nonatomic) Cards *cards;
@end