NS_INLINE and Xcode debugger - objective-c

Single stepping through code that uses any of the NS_INLINE functions from NSGeometry.h causes the debugger to lose sync with the current instruction pointer, making debugging the routines very difficult.
I've tried #undef NS_INLINE at the top of my implementation file,#define NS_INLINE in the precompiled header, looking for pragmas, compiler switches, etc., but no matter what, the functions always compile inline for my debug builds.
FWIW - NSMakeRect, NS_MakeSize, etc. all compile inline.
Question is, how do I get NS_INLINE to compile to nothing?

NS_INLINE is wrapped in #if !defined(NS_INLINE). You just need to define it appropriately before you include the Foundation headers. Glancing at the original declaration, you'll probably just need to remove __attribute__((always_inline)) for the debugger to catch your symbols (assuming you're generating all debug symbols and running a debug build - if not, then you could do a little more work to get them to all be visible. Ideally, you'll just create your own label local to your project/group/libs so you can debug your own code more easily.

Is this really about stepping through built-in API functions, or are you trying to do something similar in your own code? If it's the former, is it just due to curiosity, or some other reason for debugging? If it's the latter, I'd suggest commenting out the NS_INLINE while debugging. If you're trying to change the inlining behavior of existing API functions, you may be disappointed, and there are probably better ways to go about it. If your intent is something else, please clarify so we can answer adequately.

Related

Swift Compiler Flags Wont affect Objective-C code

under Active Compilation Conditions i have added a new flag (for debug only) called SOMEFLAG.
the check is implemented like so and works great:
#if SOMEFLAG
print("SOMEFLAG is true");
#endif
it actually prints like i would expect. now, i need to examine the same flag from Objective-C class and it never evaluates to true. any idea why?
should i make this flag in other way?
in general my goal is to be able to detect when it is executed from another target, the build is triggered from the cli.
if there is other way that less limiting i would like to know.
thanks!
In Objective-C (and other C-like languages that use a preprocessor) the canonical way to check whether a symbol is defined would be using #ifdef, not #if. There is an #if directive in Objective-C, but it doesn't behave quite the same way as the Swift #if compiler directive.

Why is #import deprecated?

I understand how #import works vs #include, the whole "Only include it if it isn't already included" thing. I also understand that Apple is pretty fond of #import for their Objective-C code, so over in Xcode it's not going anywhere and everything's fine.
What I don't get is in other environments like Android Studio, it says that #import is deprecated and gives warnings if you use it. Why is that?
It's my understanding that #import is functionally different and, in some cases, arguably better than #include, depending on what you need. If that's the case, why deprecate a potentially useful tool, especially if there isn't any sign of it being replaced with something better?
Is there some horrendous flaw in it that makes it wholly undesirable to use, or is it fine?
Because Objective-C is a superset of the C programming language, the #import statement is a minor refinement upon C’s #include statement. The #include statement is very simple; it copies everything it finds in the included file into your code during compilation. This can sometimes cause significant problems. This can creates a loop, and can confuse the compiler. To deal with this, C programmers have to write guards against this type of event from occurring.
When using #import, you don’t need to worry about this issue or write header guards to avoid it. However, #import is still just a glorified copy-and-paste action, causing slow compilation time among a host of other smaller but still very dangerous issues (such as an included file overriding something you have declared elsewhere in your own code.)
From iOS 7, Apple introduced a new way to import file:
#import UIKit;
It's a new feature called Modules or "semantic import". Modules are an attempt to get around above issue. They are no longer a copy-and-paste into source code, but a serialized representation of the included files that can be imported into your source code only when and where they’re needed. By using modules, code will generally compile faster, and be safer than using either #include or #import.
To get more information about this, you can watch WWDC 2013

How to programmatically detect automatic reference counting?

This might be a silly question, but I just wanted to know. I want my code to detect if ARC is enabled, programmatically. How do I do that? Is there is any flag that I could check? Actually the problem is that, I have written an open-source library. I have used release and retain in it. if some one else uses my library files using ARC enabled, I dont want them to get any errors. how do I achieve this? or is there any possible ways I can provide any tools to compile my library before using it?
#if !__has_feature(objc_arc)
//Do manual memory management...
#else
//Usually do nothing...
#endif
This is of course a compile-time check, you cannot check for ARC at runtime.
An alternative would be to set the -fno-objc-arc compiler flag for your files that use manual memory management in a project that otherwise uses ARC.
Whether you want to bother with this at all or just use ARC everywhere depends on how backward-compatible you want/need to be. Code that supports both ARC and MRC can get quite hard to read and maintain.
You don't detect it programmatically, it operates based on translations. That is, it is not like Garbage Collection -- which is process-wide, required all linked libraries to support (and implement it correctly in that mode). You can have some files compiled with ARC, and some without.
However, you can detect it at compilation.
As far as the distribution of your library: I would not bother with a translation based system, where ref count ops are conditionally enabled. I would (personally) just support one model (MRC in your case, until you choose to migrate it to ARC), then expect people to link to the library, or if they compile it in a target they configure, to disable ARC. Conditionally enabling/disabling code based on the presence of a feature is asking for tough bugs, particularly when it's likely to affect 9% of your library's lines of code.
NO, you can't, Xcode would not compile in ARC projects if your source uses retain-release

Objective-C: Assertion vs. Exception vs. Error

In Cocoa, when should I use NSAssert, NSException, NSError?
Here's what I've been thinking:
NSAssert - When creating any client program used for the programmers own benefit to double check rules, conventions, assumptions, or pre-conditions and post-conditions?
NSException - When creating a third-party library for the benefit of other programmers that use the library, so that they immediately know when an input is invalid?
NSError - When interfacing with an external system to get data like a file, database, or web service that isn't guaranteed to give me a result?
An NSAssert will throw an exception when it fails. So NSAssert is there to be short and easy way to write and to check any assumptions you have made in your code. It is not (in my opinion) an alternative to exceptions, just a shortcut. If an assertion fails then something has gone terribly wrong in your code and the program should not continue.
One thing to note is that NSAssert will not be compiled into your code in a release build, so this is typically used for sanity checking during development. I actually tend to use a custom assert macro that is always active.
The times you would #throw your own NSException are when you definitely want it in a release build, and in things like public libraries/interface when some arguments are invalid or you have been called incorrectly. Note that it isn't really standard practice to #catch an exception and continue running your application. If you try this with some of Apple's standard libraries (for example Core Data) bad things can happen. Similar to an assert, if an exception is thrown the app should generally terminate fairly quickly because it means there is a programming error somewhere.
NSErrors should be used in your libraries/interfaces for errors that are not programming errors, and that can be recovered from. You can provide information/error codes to the caller and they can handle the error cleanly, alert the user if appropriate, and continue execution. This would typically be for things like a File-not-found error or some other non-fatal error.
The convention in Cocoa is that an exception indicates a programmer error. A lot of code, including framework code, is not designed to work properly after an exception is thrown.
Any sort of error that should be recoverable is represented by an NSError. There’s also a system for presenting NSErrors to the user. As you say, this is mostly useful for fallible external resources.
Conceptually, an assertion is a statement that a given predicate always evaluates to true; if it doesn’t, the program is broken. While its behaviour can be modified, the NSAssert family is by default a convenient way of throwing NSInternalInconsistencyExceptions (with the option of turning them off in release builds).
Edit:
In Xcode 4.2, assertions are turned off by default for release builds,
Now NSAssert will not be compiled into your code in a release build, but you can change it in build settings
#Mike Weller, There are one wrong in your answer.
One thing to note is that NSAssert will not be compiled into your code in a release build, so this is typically used for sanity checking during development.
Actually, NSAssert will be compiled into your code if you don't add NS_BLOCK_ASSERTIONS in your precompiled prefix files.
In Technical Note TN2190 we can find:
Macros like NDEBUG to turn off C assert or NS_BLOCK_ASSERTIONS to turn off Foundation's NSAssert are important to specify for your precompiled prefix files
Or you can read this one:How to know if NSAssert is disabled in release builds?
In general, exceptions are used to signal programmer errors — they're things that shouldn't happen. Errors are used to signal error conditions that might come up in the normal operation of the program — user errors, basically, or external conditions that need to be true but might not be. So trying to delete some locked element in a document might be an error, and trying to download a file without an Internet connection would be an error, but trying to access an invalid element in a collection would be an exception.
Assertions are typically used in testing, and AFAIK are not used as a general error-handling mechanism like the others.

Why the macros in Objective-C / Cocoa?

I'm coming from a place without macros (Java/Python/C#/Scala) so perhaps my perspective is distorted but...
Why are macros used in Cocoa? Two that spring to mind are NSLocalizedString and NSAssert (and STAssert). Would it be so hard / unsuitable to make them functions (which could be inlined)? I suppose I find them a little bizarre as an unnecessary throw-back to C (and yes, I am familiar with the pedigree of Obj-C).
Is it just something that was done back in the day or is there a specific reason?
In general it is preferable to avoid macros, but for functionality like that provided by NSAssert(), you can't.
If you look at the definition, you'll see that it uses __LINE__, __FILE__, _cmd and self from the context it is used in. If it wasn't a macro, it wouldn't have access to that information.
For NSLocalizedString however, i see no obvious reason.
NSLocalizedString is a convenience macro and could probably be made a function.
However, there are good reasons why NSAssert and friends are macros besides the one given in Georg's answer. NSAssert evaluates a boolean expression to determine whether an exception should be thrown. That boolean expression might be quite computationally expensive and not the sort of thing you want to happen in your release code. There's no mechanism in C (and therefore Objective-C) of omitting normal function calls for a release build without resorting to the preprocessor or perhaps using stuff like:
if (debug)
{
assertAsAFunction(foo == 3, "foo should be 3");
}
Another advantage of the NSAssert macro is that the condition can be stringified for use in a log message.