How to detect unused methods and #import in Objective-C
Asked Answered
H

8

107

After working a long time on an iPhone app, I realized that my code is quite dirty, containing several #import and methods that are not called or useful at all.

I would like to know if there's any compiler directive or way to detect those useless lines of code. Does Xcode have any tool to detect this?

Heliogabalus answered 21/9, 2009 at 21:25 Comment(1)
This might help : iosarchitect.com/remove-unused-code-from-ios-swift-projectSmiga
R
67

Xcode allows you to (un)check settings for specific compiler warnings that can warn you of some types of unused code. (Select the project in the source list and File > Get Info, then select the Build tab.) Here are a few (which show up for Clang and GCC 4.2 for me) which may be of interest:

  • Unused Functions
  • Unused Parameters
  • Unused Values

I don't see any options for detecting unused imports, but that is a bit simpler — the low-tech approach is just to comment out import statements until you get a compile error/warning.

Unused Objective-C methods are much more difficult to detect than unused C functions because messages are dispatched dynamically. A warning or error can tell you that you have a potential problem, but the lack of one doesn't guarantee you won't have runtime errors.


Edit: Another good way to detect (potentially) unused methods is to examine code coverage from actual executions. This is usually done in tandem with automated unit testing, but doesn't have to be.

This blog post is a decent introduction to unit testing and code coverage using Xcode. The section on gcov (which only works with code generated by GCC, by the way) explains how to get Xcode to build instrumented code that can record how often it has been executed. If you take an instrumented build of your app for a spin in the simulator, then run gcov on it, you can see what code was executed by using a tool like CoverStory (a fairly simplistic GUI) or lcov (Perl scripts to create HTML reports).

I use gcov and lcov for CHDataStructures.framework and auto-generate coverage reports after each SVN commit. Again, remember that it's unwise to treat executed coverage as a definitive measure of what code is "dead", but it can certainly help identify methods that you can investigate further.

Lastly, since you're trying to remove dead code, I think you'll find this SO question interesting as well:

Residual answered 21/9, 2009 at 21:41 Comment(5)
I'm not sure what your point is... The static analyzer can find a lot of problems, but if you dispatch a message to a variable typed as id, or create a selector to call at runtime, the static analyzer can't guarantee that the code is truly unused. If code that is still needed is removed, that's where you'd get runtime errors. Am I missing something?Residual
Furthermore, selectors that are created based on strings at runtime are quite common.Rasorial
Of course, there are cases where your dynamic code might be better served by being more strongly type-cast (i.e. return something instead of an id). Runtime typing is a strong point of Cocoa/Objective-C programming, but sometimes maintenance and readability would be better served by thinking more about strong typing.Alleviation
Oh, I definitely agree. My rule of thumb is to statically type (as I would in Java) unless I really need dynamic typing, which is rare but happens on occasion. However, just interfacing with Cocoa classes (for example, specifying a delegate) can result in hard-to-trace dynamism and execution paths. Heck, any program with a run loop and multiple threads can be non-trivial...Residual
Pretty good writeup on how to clean up projects in CI etc medium.com/@mshcheglov/…Larocca
I
44

Appcode has a code inspection feature which finds unused imports and code.

Ionization answered 10/4, 2013 at 2:46 Comment(3)
So, you mean we should install Appcode just for this feature?Haematin
If it's useful to you, yes!Strive
If you're working on an old legacy project with hundreds of objc files then it's faster to install AppCode and run the unused import analysis than do this manually... :)Gard
R
11

We've been using some homegrown Ruby code, now extracted into a gem called fui: https://github.com/dblock/fui

Riker answered 22/1, 2014 at 18:30 Comment(1)
Simple and powerful, thanks.Razid
A
6

As paddydub said, AppCode do this very well. I tried, and it took me just 10 minutes :

Go to Code > Optimize Imports..., or ^ + ⌥ + O

Here is a video describing how to do this : Detection of unused import and methods in AppCode

Astronautics answered 30/5, 2014 at 13:39 Comment(0)
J
5

I recently wrote a script to find unused (or duplicate) #import statements: https://gist.github.com/Orangenhain/7691314

The script takes an ObjC .m file and starts commenting out each #import line in turn and seeing if the project still compiles. You will have to change BUILD_DIR & BUILD_CMD.

If you are using a find command to let the script run over multiple files, make sure to use a BUILD_CMD that actually uses all those files (or you will see a file with lots of unused import statements).

I wrote this without knowing AppCode has a similar feature, however when I tested AppCode it was not as thorough as this script (but way faster [for a whole project]).

Jointless answered 28/11, 2013 at 12:52 Comment(1)
It is working for duplicates only, unused imports are not getting removed.Climb
T
2

You can use Xcode Analyser to find that and other problems.

http://help.apple.com/xcode/mac/8.0/#/devb7babe820

Also you can go to the project and target build and add change warnings preferences under build settings. See this guide:

http://oleb.net/blog/2013/04/compiler-warnings-for-objective-c-developers/

Triazine answered 27/5, 2016 at 8:17 Comment(1)
I wish the analyzer reported unused imports, but it does not appear to.Serrulate
M
1

Recently, I changed a large project from Carbon to Cocoa. At the end of this, there were quite a few orphaned files that were no longer used. I wrote a script to find them that essentially did this:

Ensure the source is all checked in to subversion (ie clean) Ensure it currently builds without error (ie, xcodebuild returns 0 status) Then, for each source file in the directory, empty (ie, remove the contents, truncate the length) the source and the header file, try a build, if it fails, revert the files, otherwise, leave them empty.

After running this, revert and then delete all emptied files, compile and then remove all erroring #imports.

I should also add, you need to avoid files that are referenced from .xib or .sdef files, and there may be other dynamic linking cases, but it can still give you a good lead on what can be deleted.

The same technique can be used to see which #imports can be removed - instead of truncating the file, remove each #import in the file in turn and see if the build fails.

Monosymmetric answered 23/9, 2009 at 1:11 Comment(0)
B
-1

U can use the clang-check tool to check single c base file. For example, commit one import line and run clang-check check the file, if no error then remove the import line.

Bobine answered 8/4, 2022 at 8:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.