I need to do parsing of some Objective-C headers.
I've tried using Doxygen and parsing the XML output, but it doesn't fully support Objective C headers without comments (it chokes on macros defined in properties, check Doxygen not properly recognizing properties)
I've also tried using appledoc, but the XML output is not complete enough (for example, there is no information of inheritance for classes) and it has the same problem with macros on properties.
I've also tried parsing the output of the library Objective C metadata (using otool), but noticed that the metadata doesn't keep the types on methods (so you get method:(id)param:(id))
Does anyone know a good tool to do what I want? I'm suspecting clang will help me, but so far the -ast-dump and similar options just tries to generate an AST for a source I don't have (only headers).
You may be able to use libclang. libclang is a programmatic interface designed for implementing tools like syntax highlighting and code completion.
clang -ast-dump works for me. (Note that -ast-dump is not supported by the driver, so you have to do some extra work to pass the flags that the driver usually handles. You can use clang -### ... to see exactly what the driver is doing.)
% clang -cc1 -ast-dump -fblocks -x objective-c /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h
[...]
|-ObjCInterfaceDecl 0x1023727c0 <line:50:1, line:96:2> NSObject
| |-ObjCProtocol 0x102371350 'NSObject'
[...]
I think using clang sounds way too hard. I would just use RegEx.
Instead I would write a simple shell script wrapper around Doxygen that comments out the problematic syntax.
It should be pretty simple to change:
#property(nonatomic, retain) BOOL myProperty NS_AVAILABLE_IOS(3_2);
To:
#property(nonatomic, retain) BOOL myProperty /*NS_AVAILABLE_IOS(3_2)*/;
You could even convert things like NS_DEPRECATED() to an #deprecated comment.
Related
so, everyone If I write a property, but I don't use.
for example:
#property (nonatomic,strong) NSMutableArray *array;
but,I don't use array. so How can I check the variable like'array'?
In addition to the mentioned tools, AppCode does it very well. It will analyze the code if you open a file, or as you type it, and it will visually show that the variable is unused.
There are multiple ways to ensure your code quality. You can detect such issue by using the following methods.
Xcode's Analyze function
Linting the language you use
oclint
SwiftLint
Using Sonarqube to detect code smells and enforcing quality gate
SonarQube
I am a novice in Objective-C and I am trying to understand how pre-defined methods work. I went through the documentation of XCode and the *.h files where the method is defined. However I am eager to read the *.m file or any other document that can help me understand how the method works.
For instance - isEqualToString:(NSString *) checks if two strings (of the type NSString) are equal or not. I am not satisfied with this description. I am eager to see how the method works internally or what is the algorithm it follows. Where can I find this information?
Thank you for your help.
isEqualToString:(NSString *) is a method defined in the NSString class. Apple provides you with the framework, but they do not provide the implementation of those methods. Therefore, you can't see the source behind the standard framework's libraries.
Edit: you can create a binary and use this app to check the assembly code: http://itunes.apple.com/us/app/hopper-disassembler/id422856039?mt=12
Unfortunately, a lot of the implementation (.m) files for Apple's frameworks aren't provided publicly. You have a couple alternatives:
As Matthias suggested in a comment, use the debugger and inspect the assembler code generated for that method.
Browse through the repositories for the GNUstep project, which has some equivalents to Apple classes.
Please forgive me if this is an obvious question or if there are any errors. I am very new to Objective-C and have kind of been thrown in the deep end.
I am looking into Objective-C obfuscation. On simple method of this that I found here is to user the preprocessor to change method names to gibberish. My question is whether a decompiler can recognize preprocessor statements, such that it would be able to decompile the source back to the original method names. The example from the above referenced question is below:
#ifndef DEBUG
#define MyClass aqwe
#define myMethod oikl
#endif
#interface MyClass : NSObject {
}
- (void)myMethod;
Is it possible for, when not compiled for debugging, this code could be decompiled back to anything other than
#interface aqwe : NSObject {
}
- (void)oikl;
You could absolutely not un-obfuscate that. The preprocessor runs before the compiler gets its greasy paws on the code, so it's just as if you had manually gone through and replaced all occurrences of MyClass with aqwe, etc.
Although, you should ask yourself why you want to do this. It's just obfuscation remember, rather than actually securing anything about your code. People could still look and see the code that each method comprises. You're just changing the name of symbols.
You'll save yourself a lot of time, pain and trouble if you just choose to use one the many existing obfuscators availible instead of trying to reinvent the wheel.
Take a look at this thread, you'll find lot of useful information for a starter:
https://stackoverflow.com/questions/337134/what-is-the-best-net-obfuscator-on-the-market
Objective-C has directives like:
#interface
#implementation
#end
#protocol
#property
#synthesize
I think of these things like sophisticated marco or code-generators. Is it possible to create custom directives for code-generation purposes? One possible use is generating methods for CoreData.
I'm thinking not, because I've never seen anything about it, but my world isn't the world.
Followup Question:
Jonathan mentioned below that it is possible to write your own preprocessor and this begs the question of how. Currently, #define SYMBOLIC_CONSTANT 102 will replace all instances of the characters SYMBOLIC_CONSTANT with the characters 102 in the file before the files moves on to the compiler.
I know it XCode you can add a "Run Script Phase" to a Targets build process. So I could write a script to find my custom preprocess directives like '$coredata' and then have the script generate a new file that with the characters $coredata replaced with some characters of code. But from what I understand of XCode's build process you can't feed altered files into the Compiler Sources phase. The files are specified and locked by the IDE.
Has anyone done something similar? I know it's possible with external build system, but to be honest I'm not at that level of understanding. I don't know the technical details of what the Build and Run button does.
In the meantime, I'll start reading Apple's XCode Documentation...
Thanks for the responses!
While accepted answer is right, there is a partial hacky solution to this kind of a problem, which libextobjc library adopts. Consider this code, you will find the definitions like the following there:
#define weakify(...) \
try {} #finally {} \
metamacro_foreach_cxt(ext_weakify_,, __weak, __VA_ARGS__)
Such definition allows using weakify keyword in the following form:
id foo = [[NSObject alloc] init];
id bar = [[NSObject alloc] init];
#weakify(foo, bar);
The author of library explains it here:
Since the macros are intended to be used with an # preceding them
(like #strongify(self);), the try {} soaks up the symbol so it doesn't
cause syntax errors.
Updated later
From now on libextobjc uses #autoreleasepool to "soak up the symbol".
Your thinking is correct: it is impossible to do this in your code. The only way to add more #-directives is via the compiler itself. Even if you went to all that trouble, I can almost guarantee that the syntax highlighting support for them is hard-coded into an Xcode configuration file somewhere.
Oh, and if you were considering the use a pre-processor macro, it is my understanding that the # character is illegal in pre-processor macros.
Edit: I ran a test, and I am correct. Using the # character in a C preprocessor macro is illegal. They follow the same rule as variable names.
You mean within the bounds of Objective-C? No, as it has no way to recognize your new keywords. You could write a preprocessor to detect #whatever and convert it to code, but if you tell us what specifically you'd like to do, we may be able to suggest a more efficient or optimal approach.
It is not possible. These are keywords built into the Objective-C language. Just because there is an # in front of them doesn't make them different from other keywords.
Can I, in the GNU Objective-C runtime, attach semi-arbitrary pieces of data to instance variables?
Challenge:
I'm currently working on a kind of Cocoa workalike for Linux, as a sort of pet project. (Please, let's not get sidetracked by all the "use GNUStep" stuff. I know about it, but it doesn't suit my needs. Moving on…) For this purpose I'm trying to cobble together a simple ORM system, reminiscent of DBIx::Class for Perl. The general idea is to make the declaration as simple (read: short) as possible, and if at all possible, without the need to provide +(id)constantClassAttribute methods for overriding.
The general idea is to declare my result classes as follows:
#interface SomeTable : ORMResult {
unsigned long long id;
ORMResult *toOneRelation;
ORMResultSet *toManyRelation;
}
#end
So far, so hoopy. I can now access these fields using [ORMResult self]->ivars, and do all manner of nasty stuff, like automagically generating accessors like -[toManyRelation] or -[setToOneRelation]. Piece of cake. Unfortunately, there are two pieces of information I cannot add using this setup; one is simple enough to solve, the other not so much:
What is the actual result class?
This is solved by subclassing ORMResult (like SomeTable), and plugging that in
there, using runtime dynam(ag)ics to figure out it's to-ness (toMany, toOne).
(And this is the tricky one!) Is the relationship nullable?
This is less easily solved. My initial ideas were
(ab)using protocols, like so:
#interface SomeTable : ORMResult {
unsigned long long id;
ORMResult <ORMNullable> *toOneRelation;
}
#end
This compiles, but unfortunately, when I try to use GDB to inspect the
ivars->ivar_list entries I find that the protocol information isn't actually kept
for the runtime to toy with. This makes, I suppose, some kind of twisted sense,
as protocol declarations are mostly for the compiler.
Abusing the protocol identifiers (byref, bycopy and friends, using defines:
#interface SomeTable : ORMResult {
unsigned long long id;
nullable OMRResult *toOneRelation;
}
#end
This has the rather obvious drawback of not actually working, as these
specifiers apparently only work in protocol method declarations.
The question, then, is how can this attachment of information to the ivars be pulled off in practice?
Note: As mentioned initially, I'm using the GNU Objective-C runtime, as supplied by GCC on Linux; and not the one supplied by Apple!
Edit: Starpox! I forgot a central point: An alternative, of course, is to simply make all relations nullable. This I don't really want, but if no other alternative exists, I guess that's the path I'll end up going down.
Well, how we used to do this in ye olde days on the Mac was to create a global variable holding an NSMutableDictionary into which we put the data we want to attach to an object. Simply use a string representation of the pointer as the key.
The only difficulty becomes figuring out when an object has gone away and making sure that its entry in the dictionary is removed as well. You may have to resort to hackery like method swizzling -dealloc to achieve that.
You might look at objc_setAssociatedObject and friends, which allow you to attach arbitrary data to an object. However, I'm not sure if they're supported in the version of libobjc that you're running.