【问题标题】:Hiding types from Objective-C framework header files从 Objective-C 框架头文件中隐藏类型
【发布时间】:2012-01-07 14:17:25
【问题描述】:

我正在为我正在进行的项目编写媒体播放器框架。这取决于 VLC。我的一个类的头文件如下所示

#import <vlc/vlc.h>

@interface MediaPlayerVLC : MediaPlayer
{
    libvlc_media_player_t *player;
    libvlc_media_t *media;
}

@end

我需要类中的实例变量,并且我需要#import &lt;vlc/vlc.h&gt;,因为它们是在其中定义的。但我不希望这个框架的用户必须只为这两种类型导入所有 VLC 的头文件。我已经看到了一些解决这个问题的方法......

  • 转发声明,如@class。不幸的是,这些类型是 typedef struct 类型,我似乎找不到任何方法来转发声明它们
  • 将 ivars 声明为 void *,然后在我想使用它们时将它们转换。如果可能的话,我想避免这种情况,因为我们失去了类型安全性并且实现文件变得充满了丑陋的演员表。
  • 我在 Apple 的框架中看到过这种情况...

    @interface CAAnimation : NSObject <NSCoding, NSCopying, CAMediaTiming, CAAction>
    {
    @private
      void *_attr;
      uint32_t _flags;
    }
    

    _attr 指向什么?我想这将是一个 ivars 的结构,我很好奇这有什么优势......

  • 类的两个头文件,一个是公共的,一个是私有的。私有的看起来像上面那样,而公众只有void * 指针。这很难看,因为我必须非常小心地让它们保持同步。

什么是最佳实践?有没有我错过的方法?

【问题讨论】:

    标签: objective-c cocoa frameworks header-files


    【解决方案1】:

    您可以使用类扩展。您应该尝试这样做:

    MediaPlayerVLC.h:

    @interface MediaPlayerVLC : MediaPlayer
    {
    }
    
    @end
    

    MediaPlayerVLC.m:

    #import "MediaPlayerVLC.h"
    #import <vlc/vlc.h>
    
    @interface MediaPlayerVLC ()
    {
        libvlc_media_player_t *player;
        libvlc_media_t *media;
    }
    
    @end
    
    @implementation MediaPlayerVLC
    
    // The implementation
    
    @end
    

    来自Apple's docs

    类扩展类似于匿名类别,除了 他们声明的方法必须在主 @implementation 中实现 阻止相应的类。
    使用 Clang/LLVM 2.0 编译器, 您还可以在类中声明属性和实例变量 扩展名。

    这是使用类扩展类别在实现文件中声明额外的 ivars。

    【讨论】:

    • +1,我什么时候可以在类扩展中声明 ivars?我一定错过了。
    • 当然没问题。作为参考,因为非脆弱实例变量 (en.wikipedia.org/wiki/…) 支持已添加到 LLVM。
    • 对于这个主题也很好读:cocoawithlove.com/2010/03/…,但是类扩展中的 ivars 没有涵盖在那里,所以我不知道,它是这样工作的。
    • @implementation 和类扩展中的 ivar 比添加非脆弱 ivar 支持更新...
    【解决方案2】:

    使用最新的编译器,您还可以在类的 @implementation 部分中声明 ivars:

    // MediaPlayerVLC.m
    
    #import "MediaPlayerVLC.h"
    #import <vlc/vlc.h>
    
    @implementation MediaPlayerVLC
    {
        libvlc_media_player_t *player;
        libvlc_media_t *media;
    }
    
    ...
    
    @end
    

    【讨论】:

    • 可以吗?从来没有听说过。疯狂的东西......很高兴知道。
    【解决方案3】:

    您可以像这样将 ivars 放入实现中

    @implementation Something
    {
        int a;
    }
    

    【讨论】:

      猜你喜欢
      • 2013-07-27
      • 2011-01-07
      • 2019-11-14
      • 1970-01-01
      • 2014-09-10
      • 2015-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多