I'm working on a project that help me to convert the music file tags encoding from GBK, GB2312, JIS,UTF16 to UTF8~~~ iTunes (or whole mac world) only support UTF8 Encoding~ So to avoid the scrambled text, the music file tag's encoding has to be transcoded. (Actually, not only the music the subtitle of movies also need to be transcoded before used on Mac.)
I tried include the code into my code, but it fails to compile, it reports a lot error similar to the following:
I realize the problem is that Objective-C is only a extension of C, so it doesn't support the keyword class and similar thing. So I can just rename the file .m to be .mm, which represents Objective-C++ source file. So XCode knows that and try to compile it as a Objective-C code mixed with C++ code instead of to process it as pure Objective-C code. It works well in my code.
But the problem continues, I import the TagLib's header files in my .h file, which cause the C++ definition spreads all over the project. I have no option but rename all of my .m files to .mm.
Later, I found a bigger problem, XCode compiles .mm file may be 2x slower than .m file. And only 2 source files were involved C++ code( I wrote a Objective-C wrapper for TagLib fileref and tags, which only expose the features that I needed, it is similar to a façade pattern).
I'm not sure whether if the problem is caused by include TagLib's header file everywhere, and which is not pre-compiled ( maybe I should included it in to the pch definition? I'm no idea~ )
So I wish I can avoid to use .mm extension in most of my code. So I try to expose TagLib types in my .h file, which means I cannot use TagLib types as property or even private fields!
It is somehow difficult, but I still did it!
This is my definition .h file
//
// MediaFileInfo.h
// Transcoder
//
// Created by TimNew on 11/13/10.
// Copyright 2010 Windy's. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "NSString.TagLibIntegeration.h"
@interface MediaFileInfo : NSObject {
NSString *filePath;
NSString *title;
NSString *album;
NSString *artist;
}
@property (retain,readonly) NSString* filePath;
@property (retain, readonly) NSString *title;
@property (retain, readonly) NSString *album;
@property (retain, readonly) NSString *artist;
- (id) initWithFilePath:(NSString *) file;
- (id) initWithFilePath:(NSString*) file update:(BOOL) update;
- (void) refresh;
@end
You can find that there is no TagLib stuff at all. I moved all import instruction to the .mm file instead of put it in the .h file.
Still now everything should go well. But unfortunately it didn't!
The reason is that I import the NSString.TagLibIntegeration.h file. I just wrote a category to extend NSString, so I easily convert between NSString to TagLib::String.
//
// NSString.TagLibIntegeration.h
// Transcoder
//
// Created by Wen Di on 11/13/10.
// Copyright 2010 Windy's. All rights reserved.
//
#import <Cocoa/Cocoa.h>
namespace TagLib {
class String;
}
@interface NSString (TagLibIntegeration)
- (id) initWithTagLibString:(TagLib::String) tagLibString;
- (TagLib::String) ToTagLibString;
@end
I try to introduce TagLig/tstring header to my code, so I try to declare a stub for TagLib::String type~ It works well, but doesn't solve the problem at all. It is obvious that I use the keyword "class"!
So which require every source file imported this header to be .mm file again.
After I analyze the code, it is very lucky that I found that I only used this two methods only while I need to work the TagLib types directly, which means that except the MediaFileInfo.mm, there is no source file need to import this NSString.TagLibIntegeration header file.
So once again, I moved the import instruction from MediaFileInfo.h to MediaFileInfo.mm.
Now, everything goes well! I only introduced 2 .mm files and solved all problems!
Conclusion:
1. Avoid to import every header files in .h file, only import declaration related .h file, all others can be import in .m or .mm file.
2. When necessary, a stub definition can be used instead of import specific .h file.
3. Wrap the 3rd party types if possible, which might avoid the 3rd party types spread into our own code, which might increase the dependency of our code to 3rd party's code, which is a potential rick.
4. Always remember, Objective-C is an extension to C, not C++, so all C++ keywords such as class, const, virtual are not available.
TimNew
------------
Release your passion
To Realize your potential
I am a pessimist, I feel I'm living in a world without light.
But I am also a prayer, I believe I’m going towards a world full of sunshine!
没有评论:
发表评论