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
Related
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.
Let me start by saying I am not sure if this belongs here or at Super User. I started here.
Now, I am a very tidy person, and I like collapsing methods so that I can get around very easily. However, one thing that aggravates me is that all my #synthesize commands are always there. I can see no way to collapse them. (I have over 50 properties to synthesize) Is there a way I can hide these commands, while not messing up my build.
Thanks.
Unfortunately, from "available features" perspective, XCode is a very old IDE. Therefore no foldable code regions - see detailed discussion Xcode regions
Also note that with the latest compiler (LLVM 4.0), declaring #synthesize is optional. You can enable/disable it in compiler settings in your project settings.
However, if you are using GCC or an older LLVM version (for whatever reasons), this is not possible.
Edit:
After rereading your question... having 50 properties in one class smells very bad. Consider splitting your class into several smaller classes.
You can also put the #synthesize commands to the end of the #implementation file.
Since Xcode 4.4 you don't need to #synthesize properties if you don't want another name for it — it uses auto synthesise.
I handled several issues recently when working on my company's iOS project using XCode 4.2 and Apple LLVM complier 3.0 / LLVM-GCC.
Below is the code
A.h
#interface A{
int _count;
};
#property(nonatomic,assign) count;
#end
A.mm
#implementation A
#synthesize count = _cont;//note a typo here !!!
//... I use _count in below code
#end
The typo will not generate a compile error or warning, the compiler or run-time (actually I am not sure who did it, to my best guess should be the compiler) will generate a _cont instance ivar for us.
This feature is great for encapsulation. Our header files could be much cleaner. However such a typo is hard to notice. So I am wondering if are there any setting to generate warning for this case? I search Clang's official site without any finding.
Someone would suggest me to not declare the instance in class interface at all and always use self.count. first I don't like this code style, second there are cases your "setCount" method may do something more than just change the instance value,lastly we began our product before this feature is introduced. I don't want to change exist code's style.
Does anyone here encounter the same problem? Are there any good ideas and best practice ?
This is not possible. How should the compiler recognize your typo?
Also you should have recognized that it is not necessary to write your own ivar for your property anymore, as #synthesize count = _count; is already enough to reach you iVar via _count later in the code.
I'm using the following lines to declare a property in my objective-c program.
#property (retain) int Money;
and the syntesize in my implementation file.
Now i wanted to make an addMoney method in my implementation to add an amount of money in my program. I was typing addMoney when i realized that Xcode was saying there is always a method with this name that i could override. It has the following signature.
-(void)addMoney:(NSSet *)objects;
and
-(void)addMoneyObject:(object-type *)object
where do they come from and who is calling them? AND how could i use it by myself? What must i attend to when using this?
This method does not actually exist. Xcode is helping you out by completing some common naming patterns. It's somewhat common to have a situation like this:
#class Thing;
#property (nonatomic, retain) NSMutableSet *things;
- (void)addThings:(NSSet *)someThings;
- (void)addThing:(Thing *)aThing;
Xcode is just trying to make it a little easier to type that. But the methods don't really exist unless you create them.
Side note: you can't retain an int, so I assume this isn't real code. That's fine. Do make sure your properties start with a leading lowercase (money). It's not just individual style. ObjC relies on Key-Value Coding for many things. That requires that things be named in a certain way or it won't work.
Is Money a ManagedObject (Core Data object)? If so, that method may be being created for you. Synthesized properties should provide setter and getter but that method would look like -(void)setMoney:(int)money and -(int)Money
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.