Effective Objective-C 2.0:Item 15: Use Prefix Names to Avoid Namespace Clashes

原创 2013年12月06日 11:59:16

可惜没有指出怎么改第三方library名字的具体操作

找了下资料,觉得下面这个应该靠谱,没试验过~~ 用到时侯再研究
http://stackoverflow.com/questions/6940384/how-to-deal-with-symbol-collisions-between-statically-linked-libraries/6940389#6940389


Item 15: Use Prefix Names to Avoid Namespace Clashes

Unlike other languages, Objective-C has no built-in namespace feature. For this reason, it is easy for names to clash unless measures are taken to avoid the potential. The impact a naming clash has on an application is that it may not link, owing to duplicate symbol errors like this:

duplicate symbol _OBJC_METACLASS_$_EOCTheClass in:
    build/something.o
    build/something_else.o
duplicate symbol _OBJC_CLASS_$_EOCTheClass in:
    build/something.o
    build/something_else.o

This error results because the symbol for the class and metaclass (seeItem 14) symbols for a class called EOCTheClass have been defined twice, from two implementations of a class called EOCTheClass in twoseparate parts of the application’s code, perhaps from two separate libraries that you are pulling in.

Even worse than not linking would be if one of the libraries that contained one of the duplicates were loaded at runtime. In this case, the dynamic loader would encounter the duplicate symbol error and most likely bring down the entire application.

The only way to avoid this problem is to use a crude form of namespacing: prefixing all your names with a certain prefix. The prefix you choose should be relevant to your company, application, or both.For example, if your company were named Effective Widgets, you might decide to use the prefix EWS for code common to all your applications and EWB for code just for the application called Effective Browser. It’s still not impossible to have clashes when you prefix your names, but it is much less likely.

If you are creating applications using Cocoa, it is important to note that Apple has stated that it reserves the right to use all two-letter prefixes, so you should definitely choose a three-letter prefix in this case. For example, an issue could have arisen by not following these guidelines and deciding to use the TW prefix. When the iOS 5.0 SDK came out, it brought along the Twitter framework, which too uses theTW prefix, which has a class called TWRequest for making HTTP requests to the Twitter API. You could very easily also have had a class called TWRequest if you had an API of your own, for a company called Tiny Widgets, for example.

The prefixing should not stop with class names but should apply to all names that you have within your application. Item 25 explains the importance of prefixing category names and the methods within them if the category is on an existing class. Another important and often overlooked potential for conflict is pure C functions or global variables you use within the implementation files of your classes. It’s often easy to forget that these will appear as top-level symbols within your compiled object files. For example, the AudioToolbox framework in the iOS SDK has a function for playing a sound file. You can give it a callback that gets called when it finishes. You might decide to write a class to wrap this up into an Objective-C class that calls a delegate when the sound file finishes, like so:

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

@class EOCSoundPlayer;
@protocol EOCSoundPlayerDelegate <NSObject>
- (void)soundPlayerDidFinish:(EOCSoundPlayer*)player;
@end

@interface EOCSoundPlayer : NSObject
@property (nonatomic, weak) id <EOCSoundPlayerDelegate> delegate;
- (id)initWithURL:(NSURL*)url;
- (void)playSound;
@end

// EOCSoundPlayer.m
#import "EOCSoundPlayer.h"
#import <AudioToolbox/AudioToolbox.h>

void completion(SystemSoundID ssID, void *clientData) {
    EOCSoundPlayer *player =
        (__bridge EOCSoundPlayer*)clientData;
    if ([player.delegate
            respondsToSelector:@selector(soundPlayerDidFinish:)])
    {
        [player.delegate soundPlayerDidFinish:player];
    }
}

@implementation EOCSoundPlayer {
    SystemSoundID _systemSoundID;
}

- (id)initWithURL:(NSURL*)url {
    if ((self = [super init])) {
        AudioServicesCreateSystemSoundID((__bridge CFURLRef)url,
                                         &_systemSoundID);
    }
    return self;
}

- (void)dealloc {
    AudioServicesDisposeSystemSoundID(_systemSoundID);
}

- (void)playSound {
    AudioServicesAddSystemSoundCompletion(
        _systemSoundID,
        NULL,
        NULL,
        completion,
        (__bridge void*)self);
    AudioServicesPlaySystemSound(_systemSoundID);
}

@end

This looks completely innocuous, but looking at the symbol table for the object file created from this class, we find the following:

00000230 t -[EOCSoundPlayer .cxx_destruct]
0000014c t -[EOCSoundPlayer dealloc]
000001e0 t -[EOCSoundPlayer delegate]
0000009c t -[EOCSoundPlayer initWithURL:]
00000198 t -[EOCSoundPlayer playSound]
00000208 t -[EOCSoundPlayer setDelegate:]
00000b88 S _OBJC_CLASS_$_EOCSoundPlayer
00000bb8 S _OBJC_IVAR_$_EOCSoundPlayer._delegate
00000bb4 S _OBJC_IVAR_$_EOCSoundPlayer._systemSoundID
00000b9c S _OBJC_METACLASS_$_EOCSoundPlayer
00000000 T _completion
00000bf8 s l_OBJC_$_INSTANCE_METHODS_EOCSoundPlayer
00000c48 s l_OBJC_$_INSTANCE_VARIABLES_EOCSoundPlayer
00000c78 s l_OBJC_$_PROP_LIST_EOCSoundPlayer
00000c88 s l_OBJC_CLASS_RO_$_EOCSoundPlayer
00000bd0 s l_OBJC_METACLASS_RO_$_EOCSoundPlayer

Note the symbol lurking in the middle, called _completion. This is the completion function created to handle when the sound has finished playing. Even though it’s defined in your implementation file and not declared in the header file, it still appears as a top-level symbol like this. Thus, if another function called completion is created somewhere, you’ll end up with a duplicate-symbol error when linking, such as the following:

duplicate symbol _completion in:
    build/EOCSoundPlayer.o
    build/EOCAnotherClass.o

Worse still would be if you were shipping your code as a library for others to use in their own applications. If you exposed a symbol called_completion like this, anyone using your library would not be able to create a function called completion, which is a nasty thing for you to do.

So you should always prefix C functions like this as well. In the preceding example, you could call the completion handlerEOCSoundPlayerCompletion, for example. This also has the side effect that if the symbol ever appears in a backtrace, it’s easy to determine what code the problem has come from.

You should be particularly careful of the duplicate-symbol problems when you use third-party libraries and ship your code as a library that others plug into their own applications. If the third-party libraries that you use are also going to be used by the application, it’s easy for duplicate-symbol errors to arise. In that case, it’s common to edit all the code of the libraries you use to prefix them with your own prefix.For example, if your library is called EOCLibrary and you pull in a library called XYZLibrary, you would go through and prefix all names in XYZLibrary with EOC. The application is then free to useXYZLibrary itself, without the chance of a naming collision, as shown in Figure 3.1.

Image

Figure 3.1 Avoiding naming clashes where a third-party library is included twice: once by the application itself and once by another library

Going through and changing all the names might seem like a rather tedious thing to do, but it’s prudent if you want to avoid naming collisions. You may ask why it’s necessary to do this at all and why the application can’t simply not include XYZLibrary itself and use your implementation of it. It’s possible to do that as well, but consider the scenario in which the application pulls in a third library, ABCLibrary, that has also decided to use XYZLibrary. In that case, if you and the author of ABCLibrary hadn’t prefixed, the application would still get duplicate-symbol errors. Or if you use version X of XYZLibrary but the application requires features from version Y, it would want its own copy anyway. If you spend time using popular third-party libraries with iOS development, you will frequently see this kind of prefixing.

Things to Remember

Image Choose a class prefix that befits your company, application, or both. Then stick with that prefix throughout.

Image If you use a third-party library as a dependency of your own library, consider prefixing its names with your own prefix.

编写高质量的iOS代码--Effective Objective-C 2.0 读书笔记

编写高质量的iOS代码--Effective Objective-C 2.0 读书笔记 这本书年初刷完,感觉不错,介绍了很多小点,都是平日不怎么关注的. 第1章 熟悉Objective-C...
  • uxyheaven
  • uxyheaven
  • 2014年12月26日 23:56
  • 5049

Effective Objective-C 2.0 读书笔记

第 1 章 熟悉 Objective-C 第 2 章 对象消息运行时 第 3 章 接口和 API 设计 第 4 章 协议与分类 第 5 章 内存管理 循环引用 普通的两个变量互相引用 Block 循环...
  • xsl_bj
  • xsl_bj
  • 2016年06月06日 12:27
  • 4768

Effective Objective-C 2.0:Item 20: Prefix Private Method Names

Item 20: Prefix Private Method Names It’s extremely common for a class to do much more than it ap...
  • chuanyituoku
  • chuanyituoku
  • 2013年12月07日 17:50
  • 904

【Effective Objective-C 2.0读书笔记】第三章:接口和API设计

一旦你完成了一个应用,你可能会希望在以后的工程中重用部分代码。你也可能会发布一些代码以供其他人来使用。这意味着你需要使用Objective-C的范式和理解众多的陷阱。...
  • freeWayWalker
  • freeWayWalker
  • 2015年07月06日 15:23
  • 592

iOS-Effective Objective-C 2.0 读书笔记(三)

第三章的内容主要是说接口和API设计相关的注意事项。比如说我们自己写的代码需要设计以便于代码复用时,应该注意的一些问题包括哪些。简单总结  有些注意事项实际上很简单,而且很常见,我觉得并不需要太长篇幅...
  • linyousong
  • linyousong
  • 2016年04月29日 22:31
  • 413

阅读《Effective Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法》总结

第1条:了解Objective-C语言的起源 Objective-C为C语言添加了面向对象特性,是其超集。Objective-C使用动态绑定的消息结构,也就是说,在运行时才会检查对象类型。接收一...
  • caojengineer
  • caojengineer
  • 2015年06月07日 22:52
  • 1182

《Effective Objective-C 2.0编写高质量iOS与OS X代码的52个有效方法》读书笔记(下)

1.为避免在不经意间使用了无效对象,一般在release之后会清空指针,=nil; 2.通常利用弱引用或者“手动”解除引用的方式破坏循环引用。 3.ARC下,规定以alloc、new、copy、mut...
  • zhaochen_009
  • zhaochen_009
  • 2017年04月06日 10:44
  • 325

Error parsing XML: prefix must not be bound to one of the reserved namespace names

gradlew Error parsing XML
  • kv110
  • kv110
  • 2016年04月20日 16:06
  • 1354

Effective Objective-C 2.0:Item 26: Avoid Properties in Categories

Item 26: Avoid Properties in Categories A property is a way of encapsulating data (see Item 6)....
  • chuanyituoku
  • chuanyituoku
  • 2013年12月08日 16:37
  • 786

Effective Objective-C 2.0: Item 40: Avoid Retain Cycles Introduced by Blocks

Item 40: Avoid Retain Cycles Introduced by Blocks Referencing the Object Owning Them Blocks can v...
  • chuanyituoku
  • chuanyituoku
  • 2013年12月12日 20:41
  • 962
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Effective Objective-C 2.0:Item 15: Use Prefix Names to Avoid Namespace Clashes
举报原因:
原因补充:

(最多只允许输入30个字)