Will NSAssert takes any memory on the device in iOS? - ios

If we run the app on device with NSLogs then it may slow down the app to some extent.
Is NSAssert act in the same way as NSLog in the memory aspect?
Any comments or suggestions would be appreciated.
Thank you in advance.

Maybe this will answer your question
It's important to note that as of Xcode 4.2, assertions are turned off
by default for release builds, which is accomplished by defining the
NS_BLOCK_ASSERTIONS macro. That is to say, when compiled for release,
any calls to NSAssert & co. are effectively removed.
Source: http://nshipster.com/nsassertionhandler/
If you leave them enabled, then yes they come at a cost (obviously they need to be evaluated) and depending on what code you have them execute it differs. For simple nil comparisons it is negligible.
For further reference see: http://www.mikeash.com/pyblog/friday-qa-2013-05-03-proper-use-of-asserts.html
Specifically this passage
The runtime cost should be negligible, and if it's not, then you should redo your asserts to fix that.

In XCode, by default assertion are disabled in release, so they won't take any processing time. If you check in your build settings, NS_BLOCK_ASSERTIONS is set to 1 and looking at the NSAssert define in that case
#define NSAssert(condition, desc, ...) do {} while (0)
empty loop that will be removed at compilation time.

Related

Could Xcode affect app performance while debugging?

I have an application written in Swift on SceneKit + Metal. When I build and run the app from Xcode fps counter shows 40fps. But if I run the app myself by tapping the icon on springboard fps counter shows 60fps. How could it be? Could Xcode somehow affect app performance while debugging? I have no idea how this all works, but I suppose there could be some hooks for debugging to work correctly which affect performance. If so, can I opt-in from this?
I'm aware of different build flags for debug and release builds, but I don't make release build. Performance differs in the same debug build while running from Xcode vs when I run the app manually on the phone.
By default, Xcode enables the Metal validation layer. That does a bunch of additional checking of how you're using it to catch incorrect uses. The additional checking is slow, which is why Metal doesn't do it unless validation is enabled.
This can be changed in Xcode's Scheme editor. This is documented in Apple's Metal Programming Guide.
A nice tutorial on iOS Assembly. This might be insightful on the topic
As stated, this is because the compiler is in debug mode, meaning no optimizations are made. If you turn optimizations on, then you’ll see a much smaller function generated.
And also check out this answer about changing optimization levels.
I've experimented with different options in scheme editor and have find out that Debug executable checkbox affected performance in my case. So my assumption about debugger was right, but I didn't know about that checkbox before.

IOS/Objective-C: Removing NSLog statements for Release and Build Settings in 2018

A lot of tutorials and answers on SO from the 2008 to 2013 eras say you should remove NSLog statements before releasing an app on the Apple store due to the high overhead of NSLog.
However, by default, Apple seems to have two build configurations, Debug and Release and when you archive the app for release, it now seems to automatically assign the Release configuration.
My question is, in light of this, do you still need to remove the NSLogs or does the Release configuration now automatically do this for you?
Many of the previous answers suggest making an entry in the pch file which no longer exists by default. If you use an alternative debugger apparently you are supposed to make an entry in the Preprocessor Macros however this is beyond my level of knoweldge.
Can anyone shed some light on the preferred approach to the NSLog issue today.

Asserts are hit in production build causing crashes

I have several assert(condition, "message") statements in my project.
They are used to check invariant conditions during development. I thought they would be ignored in production/release build (as stated in this answer). They are not. Instead they cause crashes during TestFlight testing. When I comment asserts the app does not crash. Something usually gets wrong a bit but it does not crash.
Can it be something with my build settings?
All my archive schemes use release configuration:
The asserts are in Cocoa Touch Framework project, that is used from custom keyboard extension.
All the targets in all projects (Cocoa Touch Framework, and the main project with keyboard extension target) have these Build Settings:
Enable Foundation Assertions
Debug YES
Release NO
Disable Safety Checks NO
What's wrong?
EDIT:
Sulthan's answer shows how to disable asserts globally for both debug and relase builds. That is not what I need. I want it to work as expected - asserts should be enabled in debug but disabled in release builds.
By default it works that way - and it also works that way in my main project. But it does not work for asserts located in Framework project that is linked from that main project (details in this question). Why? How to fix it?
The options you have tried:
Enable Foundation Assertions is in the preprocessing section (Macros). Swift is not preprocessed and does not use macros. This option disables NSAssert, NSParameterAssert and similar macros commonly used in Objective-C.
Disable Safety Checks is a performance option:
By default, the standard library guarantees memory safety. Many functions and methods document the requirements that must be satisfied by the caller, such as an array index being valid; memory safety is guaranteed even if a requirement is violated. However, violating a requirement can trigger a runtime error. APIs that include the word “unsafe” in their name let you explicitly disable safety checks in places where you need the additional performance. It’s your responsibility to verify the memory safety of code that uses unsafe APIs. Memory safety is also not guaranteed if there is a race condition in multithreaded code.
(Swift Library Reference)
You should probably try my answer here
(use -assert-config Release in Other Swift Flags).
Or just keep the asserts in production builds. Every failing assert is a bug and in general it's better to know about a bug as soon as possible.

Swift Assertions behaviour in production applications

I'm reading the Assertions section in the Swift e-book and it looks like assertions work very similarly to their Objective-C counterparts. However, nowhere in the docs can I find anything about runtime behaviour while running as a production app. Objective-C's NSAssert promises never to terminate a production application as a result of an assertion failure. Is it the same case in Swift?
Based upon the language Apple use in their documentation, I'd say assertions are ignored in a production environment.
If your code triggers an assertion while running in a debug
environment, such as when you build and run an app in Xcode, you can
see exactly where the invalid state occurred and query the state of
your app at the time that the assertion was triggered. An assertion
also lets you provide a suitable debug message as to the nature of the
assert.
And in the "Note" block:
Assertions cause your app to terminate and are not a substitute for
designing your code in such a way that invalid conditions are unlikely
to arise. Nonetheless, in situations where invalid conditions are
possible, an assertion is an effective way to ensure that such
conditions are highlighted and noticed during development, before your
app is published.
The difference between debug and release is the difference between compiler arguments. The most likely answer is that there will be some special compiler settings (similar to -ea in Java).
EDIT
The Swift compiler has an argument called -assert-config
-assert-config Specify the assert_configuration replacement. Possible values are Debug, Release, Replacement.
In Release, the assertions are ignored. Not sure about the difference between Debug and Replacement.
Check your Optimization Level and make sure it is not Onone for release configuration. See my note https://github.com/onmyway133/blog/issues/39
Asserts are documented along with preconditions in the Swift standard library documentation.
Debug -> Stop on assertion failure.
Release -> Compile with assertions ignored
Release and "Disable safety checks" -> Assume all assertion statements are statements of truth and hints to the compiler so that following and preceding code may be removed if only reached in conditions where the assertion would have failed. This means that if you follow the assertion by code on handle the exceptional case it may be ignored. If the assertion would ever have failed the behaviour is completely undefined.
I've not checked but the "Disable safety checks" may correlate with the -assert-config Replacement that #Sulthan mentions.

ARC conversion tool issues: flagged retain/release, and random parse errors

I'm revisiting an an older project and converting to ARC, my first time through Xcode's conversion tool (Edit -> Refactor -> Convert to Objective-C ARC...), and I'm seeing a couple things that I'm not sure are real issues or red herrings somehow.
I get, as expected a big list of things that the tool finds that prevent it from completing, but:
Many (all?) instances of retain/release/autorelease appear to be flagged as errors e.g. "release is unavailable: not available in automatic reference counting mode". Am I really supposed to get rid of all these myself? I thought that's what the tool did.
In many of my classes, I'm seeing a bunch of errors that look like phantom parse/build errors that have nothing to do with ARC. E.g. in a simple class that apparently has no ARC-related issues, I'll get an "undeclared identifier" on some arbitrary method implementation, and then a bunch of "Parse error: expected }" at the end of the file, etc. These are not real-- the project builds fine, and I don't see any proximate cause or resolution for the errors.
There are "real" issues in the list as well (expected bridging issues that need to be explicitly clarified in code) but there are so many random errors of the above variety that it's hard to even find the signal in the noise. This seems wrong to me.
Am I misunderstanding what this tool is really doing? Apple's docs say this:
Xcode provides a tool that automates the mechanical parts of the ARC
conversion (such as removing retain and release calls) and helps you
to fix issues the migrator can’t handle automatically
Thanks.
The tool does not get rid of them for you, but simply adds retain/release code as need under the hood at the time of compile.
Those problems very well may go away when you get rid of old reference counting code.
EDIT: Further explanation:
In Xcode 4.2, in addition to syntax checking as you type, the new
Apple LLVM compiler makes it possible to offload the burden of manual
memory management to the compiler, introspecting your code to decide
when to release objects. Apple’s documentation describes ARC as
follows:
“Automatic Reference Counting (ARC) is a compiler-level feature that
simplifies the process of managing object lifetimes (memory
management) in Cocoa applications.”
In other words, ARC does not "strip" reference counting from your code, but rather does it on it's own under the hood. You no longer have to type release or retain or dealloc again. One thing the ARC needs to work is for it to do the reference counting entirely on it's own (with no user reference counting to "get in the way").
Took a long time to resolve, but both of these issues seemed to stem from some custom macros I was using. I had a macro for release-and-set-to-nil that I was using frequently, like this:
#define RELEASENIL(x) [(x) release]; \
(x) = nil;
I'm still not sure why, but for some reason, the ARC conversion tool didn't take this in stride, and choked on it, throwing the release warnings and the parse errors. (Some interaction with the preprocessor?) When I changed the macro to remove the release line, the conversion proceeded much more in line with my expectations.
And yes, it does of course remove the messages for you. (I'm answering my own question on the off chance that someone else ever has this issue.)

Resources