【问题标题】:Linking problems with a category on Scripting Bridge将问题与 Scripting Bridge 上的类别相关联
【发布时间】:2013-05-06 14:49:57
【问题描述】:

我正在尝试使用关联对象(一个 NSMutableDictionary 和一个 NSNumber)在 iTunesTrack 上编写一个类别

#import "iTunes.h"
#import <objc/runtime.h>

@interface iTunesTrack (dictionary)
- (NSMutableDictionary*) getDictionary;
- (NSNumber*) getScan;
- (BOOL)scanTrack:(NSString *)equationString;
@end

这失败了:

Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_iTunesTrack", referenced from:
      l_OBJC_$_CATEGORY_iTunesTrack_$_dictionary in iTunesTrack+dictionary.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我已经仔细检查了是否添加了 Scripting Bridge 框架以及是否已将 iTunesTrack+dictionary.m 文件附加到目标。将类别与脚本桥结合起来会不会是一些错误?


更新:

如果我用 SBObject 替换 iTunesTrack,这可行。不过我不知道为什么。


更新 2:

这个问题是可以重现的:

  1. 创建新项目
  2. 添加脚本桥框架和 iTunes.h 头文件。
  3. 使用任意名称创建新的 iTunesTrack 类别
  4. 确保iTunesTrack+name.h 导入iTunes.h
  5. 构建

我找到了this page,它描述了使用 NSProxy 和 NSCache 来存储 iTunesTrack 对象。这会是比尝试创建一个类别更好的解决方案吗?

【问题讨论】:

    标签: objective-c cocoa objective-c-category scripting-bridge


    【解决方案1】:

    Scripting Bridge 真是一团糟。

    iTunesTrack 类实际上被称为 ITunesTrack
    我认为它们与前导小写 i 不太一致。

    这就是为什么他们在一段时间后改变了它,但可能不想在头文件中这样做,而不是改变他们的 API。

    我认为没有办法解决这个问题。

    但是,您可以在 SBObject 上创建类别。

    // The interface can be declared as iTunesTrack
    @interface iTunesTrack (Additions)
    ...
    @end
    
    // The category MUST be implemented on SBObject
    @implementation SBObject (Additions)
    ...
    @end
    

    注意

    请注意,每个SBObject 都可以使用该类别,因此请确保所有属性和方法都具有唯一的接口。

    【讨论】:

    • NSAddict 的回答指出了做我一直想做的事情的方法:实现 - (id)debugQuickLookObject;用于 SBObject 类。
    【解决方案2】:

    您不能在 iTunesTrack(或 ITunesTrack,或任何它在您的标题中调用的)上放置一个类别,因为这要求该类在链接时存在,但它不存在:Scripting Bridge 在以下位置动态创建目标应用程序的类运行。 (从技术上讲,它们的名称是任意的,这就是-classForScriptingClass 存在的原因。)仍然可以向生成的类添加方法,但这意味着要在运行时捣乱,这通常比它的价值更麻烦。只需将您的类别方法放在SBObject 上并尽量小心。

    【讨论】:

      【解决方案3】:

      NSAddict 的回答指出了我一直想做的事情的方法:为 SBObject 类型实现 debugQuickLookObject 以使调试更容易。这是 iTunesTrack 和 iTunesArtwork 的类别。

      //  SBObject+Extensions.h
      
      @import ScriptingBridge;
      
      @interface SBObject (Extensions)
      
      - (id)debugQuickLookObject;
      
      @end
      
      
      //  SBObject+Extensions.m
      
      #import "iTunes.h"
      
      @implementation SBObject (Extensions)
      
      - (id)debugQuickLookObject
      {
          NSString *className = self.className;
      
          if ([className isEqualToString:@"ITunesTrack"])
          {
              return [self handleITunesTrack];
          }
          else if ([className isEqualToString:@"ITunesArtwork"])
          {
              return [self handleITunesArtwork];
          }
      
          return [self description];
      }
      
      - (NSString*)handleITunesTrack
      {
          iTunesTrack *track = (iTunesTrack *)self;
      
          NSMutableString *s = [NSMutableString new];
      
          [s appendFormat:@"Title:    %@\n", track.name];
          [s appendFormat:@"Artist:   %@\n", track.artist];
          [s appendFormat:@"Album:    %@\n", track.album];
          [s appendFormat:@"Duration: %f seconds\n", track.duration];
      
          return s;
      }
      
      - (NSImage*)handleITunesArtwork
      {
          iTunesArtwork *artwork = (iTunesArtwork *)self;
      
          NSData *data   = [artwork rawData];
          NSImage *image = [[NSImage alloc] initWithData:data];
      
          return image;
      }
      
      @end
      

      【讨论】:

        【解决方案4】:

        您可能会在此讨论中找到答案: linker command failed with exit code 1 (use -v to see invocation)

        您也可以尝试清理然后重新构建您的项目或转到项目 -> 构建设置 -> 有效架构并检查是否全部正确。其中一些建议可能会对您有所帮助。

        【讨论】:

        • 我试过清洁。我也刚刚尝试制作一个只添加了类别、iTunes.h 和 Scripting Bridge 的全新项目,但它仍然失败。
        猜你喜欢
        • 2012-06-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-06
        • 1970-01-01
        • 2012-10-04
        • 1970-01-01
        • 2017-07-26
        相关资源
        最近更新 更多