使用 NSString *const 为每个视图子类加载不同的媒体文件
我完全用代码(没有 IB)创建 UIView 的子类,我们称之为 ContentView。在此视图中,我已经设置了多个声音和视频播放器,以及多个图像视图(没什么特别的)。
接下来,我计划多次对 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
我无法完成这项工作。没有编译器错误或警告,只是没有播放或显示任何内容。我是否做错了什么,或者这不是解决问题的正确方法?
我真的很感激一些见解。提前致谢。
I'm making a subclass of UIView completely in code (no IB), let's call it ContentView. In this view I've already set up several players for sounds and video, as well as several imageViews (nothing special).
Next, I was planning to subclass ContentView several times in order to load different media for each view. All of these views would have the same view controller since the interface would be the same for all of them, only the content (sounds, video and images) would change.
So my approach to this problem was to declare several NSString *const
in ContentView.h and specify their keys/values in the implementation file of each subclass view of ContentView, in the form of static NSString *const
, since I would be reusing them to load different media for each view and did not want them in the global name space.
Here is some mockup code that illustrates what I'm talking about:
In 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;
and in ContentView.m, something of the sort,
@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];
... and so on, for the rest of the sound files and movies (except for the images, for which i'm using imageNamed:
).
Then on the implementation file of each subclass of ContentView I have just this:
@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
I can't make this work. There are no compiler errors or warnings, simply nothing plays or shows. Am I doing something wrong, or is this just not the right approach to the problem?
I would really appreciate some insights. Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
虽然@deanWombourne 的以下答案非常有道理,但我对他的解决方案有疑问。但我已经发现它出了什么问题(至少这是我的看法并且它现在正在工作)。
UIView 子类已经有自己指定的初始化程序,即
-(id)initWithFrame< /code>,因此在 ContentView 的任何后续子类上调用
-(id)init
不会更新任何实例变量,因为[super init]
定向到任何地方(或者更好,首先超类运行initWithFrame
,然后才运行init
,这与什么都不做相同)。所以我的解决方案如下:(
将ContentView.h上的ivars更改为
NSString *pointer
的形式后,例如NSString *kSoundFile1
),首先更新字符串在指定的初始化器
-(id)initWithFrame
上,然后才调用 super.现在效果很好。
我衷心感谢@deanWombourne 在解决这个问题时提供的帮助。
Although the answer below from @deanWombourne makes perfect sense, I had an issue with his solution. But I have found out what was wrong with it (at least this is my take on it and it's working now).
A UIView subclass already has its own designated initializer, which is
-(id)initWithFrame
, so calling-(id)init
on any subsequent subclass of ContentView is not going to update any instance variables since[super init]
directs to nowhere (or better, first the superclass runsinitWithFrame
and only then it runsinit
, which is the same as having done nothing).So my solution is the following:
(after changing the ivars on ContentView.h to the form of
NSString *pointer
, for example,NSString *kSoundFile1
),First update the strings on the designated initializer
-(id)initWithFrame
, and only then call super.It works just fine now.
My sincere thanks to @deanWombourne for the help given in solving this problem.
我想我可能已经解决了,忽略我的其他答案:)
您已将字符串设置为 ContentView 的成员(在 ContentView.h 中)。它们一开始就初始化为
nil
。然后,在每个子类中,您创建具有相同名称的新字符串,但仅在该 .m 文件中(static 关键字可以做到这一点!)。只是因为它们在 C 代码中具有相同的名称并不意味着它们指向同一个对象:)
您的 ContentView.m 文件看不到新字符串,它只使用 .h 文件中定义的字符串,从未被设置过任何东西,所以我打赌它们仍然是
nil
!您需要在子类中定义字符串,如下所示:
PS 这些名称前面的
k
不再有意义 - 我会去掉它)I think I might have worked it out, ignore my other answer :)
You've set the strings up as members of ContentView (in ContentView.h). They start out initialised to
nil
.Then, in each subclass you create new strings with the same name but only in that .m file (the static keyword does that!). Just beacuse they have the same name in the C code doesn't mean they're pointing to the same object :)
Your ContentView.m file can't see the new strings, it just uses the ones defined in your .h file, which have never been set to anything so I bet they're still
nil
!You need to define the strings in your subclasses like this :
PS The
k
in front of these names doesn't make much sense anymore - I'd get rid of it)编辑:这个答案完全是错误的树。尝试这个 相反:)
我立即寻找这一行:
SDK想要告诉你错误,但你要求它不要这样做。然后你抱怨没有错误!
试试这个:
让我们知道您看到了什么。
EDIT: This answer is completely barking up the wrong tree. Try this one instead :)
I instantly look for this line :
The SDK wants to tell you the error but you ask it not to. Then you complain that there is no error!
Try this:
and let us know what you see.