使用NSString * const为每个视图子类加载不同的媒体文件

时间:2011-06-14 11:43:29

标签: iphone objective-c xcode cocoa-touch nsstring

我在代码中完全使用UIView的子类(没有IB),我们称之为 ContentView 。在这个视图中,我已经为声音和视频设置了几个播放器,以及几个imageViews(没什么特别的)。

接下来,我计划多次继承 ContentView ,以便为每个视图加载不同的媒体。所有这些视图都具有相同的视图控制器,因为所有这些视图的界面都是相同的,只有内容(声音,视频和图像)会发生变化。

所以我解决这个问题的方法是在 ContentView .h中声明几个NSString *const,并在 ContentView的每个子类视图的实现文件中指定它们的键/值,以static NSString *const的形式,因为我将重复使用它们为每个视图加载不同的媒体,并且不希望它们出现在全局名称空间中。

这是一些模拟代码,说明了我在说什么:

在ContentView.h中

@interface ContentView : UIView {

NSString *const kSoundFile1;
NSString *const kSoundFile2;
NSString *const kSoundFileType;
NSString *const kMovieFile1;
NSString *const kMovieFile2;
NSString *const kMovieFileType;
NSString *const kImage1;
NSString *const kImage2;

并在ContentView.m中,某种类型,

@implementation ContentView 

- (id)initWithFrame:(CGRect)frame
{ 
   self = [super initWithFrame:frame];
       if (self) {

       NSString *filePath1 = [[NSBundle mainBundle] pathForResource: kSoundFile1 
                                                         ofType: kSoundFileType;

       NSURL *url1 = [[NSURL alloc] initFileURLWithPath:filePath1];

       AVAudioPlayer *audioPlayer1 = [AVAudioPlayer alloc] initWithContentsOfURL:url  error:nil];
       [audioPlayer1 prepareToPlay];
       [url1 release];

...等等,对于其余的声音文件和电影(我正在使用的图像除外imageNamed:)。

然后在 ContentView 的每个子类的实现文件中,我就是这样:

@implementation ContentViewSubclass

static NSString *const kSoundFile1 = @"sound1";
static NSString *const kSoundFile2 = @"sound2";
static NSString *const kSoundFileType = @"wav";
static NSString *const kMovieFile1 = @"movie1";
static NSString *const kMovieFile2 = @"movie2";
static NSString *const kMovieFileType = @"mov";
static NSString *const kImage1 = @"image1.png";
static NSString *const kImage2 = @"image2.png";

@end

我无法完成这项工作。没有编译器错误或警告,只是没有播放或显示。我做错了什么,或者这不是解决问题的正确方法?

我真的很感激一些见解。提前谢谢。

3 个答案:

答案 0 :(得分:1)

虽然@deanWombourne的答案非常有道理,但我的解决方案存在问题。但是我发现它有什么问题(至少这是我对它的看法,现在它正在运作)。

UIView子类已经有了自己的指定初始值设定项-(id)initWithFrame,因此在 ContentView 的任何后续子类上调用-(id)init都不会更新任何实例变量[super init]指向无处(或者更好,首先超类运行initWithFrame,然后才运行init,这与没有做任何事情相同。

所以我的解决方案如下:

(将ContentView.h上的ivars更改为NSString *pointer的格式,例如NSString *kSoundFile1),

@implementation ContentViewSubclass

- (id)initWithFrame:(CGRect)frame {

        kSoundFile1 = @"sound1";
        kSoundFile2 = @"sound2";
        kSoundFileType = @"wav";
        kMovieFile1 = @"movie1";
        kMovieFile2 = @"movie2";
        kMovieFileType = @"mov";
        kImage1 = @"image1.png";
        kImage2 = @"image2.png";

    self = [super initWithFrame:frame];
    if (self) {

    }
    return self;
}

@end

首先更新指定初始值设定项-(id)initWithFrame上的字符串,然后再调用super。 它现在运作得很好。

衷心感谢@deanWombourne在解决这个问题方面提供的帮助。

答案 1 :(得分:0)

编辑:这个答案完全叫错了树。请尝试this one:)


我立即寻找这条线:

AVAudioPlayer *audioPlayer1 = [AVAudioPlayer alloc] initWithContentsOfURL:url  error:nil];

SDK 希望告诉您错误,但您要求不要。然后你抱怨没有错误!

试试这个:

NSError *error = nil;
AVAudioPlayer *audioPlayer1 = [AVAudioPlayer alloc] initWithContentsOfURL:url  error:&error];
if (error) {
    NSLog(@"error : %@", error);
}

让我们知道你看到了什么。

答案 2 :(得分:0)

我想我可能已经解决了,忽略了我的另一个答案:)

您已将字符串设置为ContentView的成员(在ContentView.h中)。他们开始初始化为nil

然后,在每个子类中,您创建具有相同名称但仅在该.m文件中的 new 字符串(static关键字执行此操作!)。只是因为它们在C代码中具有相同的名称并不意味着它们指向同一个对象:)

您的ContentView.m文件无法看到新字符串,它只使用.h文件中定义的字符串,这些文件从未设置为任何内容,所以我敢打赌它们仍然是nil

您需要在子类中定义字符串,如下所示:

@implementation ContentViewSubclass

- (id)init {
    self = [super init];
    if (self) {
        kSoundFile1 = @"sound1";
        kSoundFile2 = @"sound2";
        kSoundFileType = @"wav";
        kMovieFile1 = @"movie1";
        kMovieFile2 = @"movie2";
        kMovieFileType = @"mov";
        kImage1 = @"image1.png";
        kImage2 = @"image2.png";
    }
    return self;
}

@end

PS这些名字前面的k已经没有多大意义了 - 我已经摆脱它了)