CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION removed? - ios

Seems like CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION was removed in Xcode 8. It provided some really good warnings in case nil was passed to nonnull parameters/return types. Any idea why this was removed and whether there exists a replacement?

I still see warning, when I pass nil to nonull expected method. Maybe it's enabled by default for now.

Related

Why does #unknown default (Swift 5) cause compile error?

I think I understand the logic behind #unknown default, and I apologize for screenshots instead of code, but it's the only way to see the error messages in context.
Converted a project to Swift 5. It runs, but gets this warning, which I understand:
So I let Xcode fix it for me, and got this:
I changed the order of the stub cases (this is a work in progress), which makes the compiler happy again:
Am I doing something I shouldn't, or is this weird compiler behavior?
The error in the middle image looks like a bug in swift and it could be solved by adding a semicolon at the end of the return statement.
In general the compiler is expecting #unknown default to be the last case. Check #unknown documentation from apple where they explain why it must be used with the last case in a switch and more on the "unknown patterns" link in the following quote:
#unknown may only be applied to default or a case consisting of the
single pattern _. Even in the latter case, #unknown must be used with
the last case in a switch. This restriction is discussed further in
the "unknown patterns" section under "Future directions".
There are many situations where a bare return followed by another line of code causes Swift to think you’re trying to return that line of code. The situation is less confusing than it used to be, because now there is at least a warning to tell you about it (and the situation arises in a much smaller range of cases than it used to):
#IBAction func doDismiss(_ sender: Any) {
return
self.presentingViewController?.dismiss(animated:true)
}
That code looks legal, but it doesn’t compile, the result being a seemingly strange compile error:
Value of optional type 'Void?' must be unwrapped to a value of type ‘Void'
Fortunately, in this instance, the reason for the strangeness is now also revealed by a warning (usually):
Expression following 'return' is treated as an argument of the 'return'
The solution has always been to add a semicolon after the return. Indeed, for those of us who have been using Swift since Swift 1, adding a semicolon after a bare return is practically a reflex action, even though it is usually no longer needed these days.
Your situation is basically a case of the same issue. The problem is that you don’t get the explanatory warning.

IfThen(Assigned(Widget), Widget.Description, 'No Widget') doesn't crash. Should it?

In code that I help maintain, I have found multiple examples of code that looks like this:
Description := IfThen(Assigned(Widget), Widget.Description, 'No Widget');
I expected this to crash when Widget was nil, but when I tested it, it worked perfectly.
If I recompile it with "Code inlining control" turned off in Project - Options - Compiler, I do get an Access Violation.
It seems that, because IfThen is marked as inline, the compiler is normally not evaluating Widget.Description if Widget is nil.
Is there any reason that the code should be "fixed", as it doesn't seem to be broken? They don't want the code changed unnecessarily.
Is it likely to bite them?
I have tested it with Delphi XE2 and XE6.
Personally, I hate to rely on a behavior that isn't contractual.
The inline directive is a suggestion to the compiler.
If I understand correctly what I read, your code would also crash if you build using runtime packages.
inlining never occurs across package boundaries
Like Uli Gerhardt commented, it could be considered a bug that it works in the first place. Since the behavior isn't contractual, it can change at any time.
If I was to make any recommendation, I would flag that as a low priority "fix". I'm pretty sure some would argue that if the code works, it doesn't need fixing, there is no bug. At that point, it becomes more of a philosophical question (If a tree falls in a forest and no one is around to hear it, does it make a sound?)
Is there any reason that the code should be "fixed", as it doesn't seem to be broken?
That's really a question that only you can answer. However, to answer it then you need to understand fully the implications of reliance on this behaviour. There are two main issues that I perceive:
Inlining of functions is not guaranteed. The compiler may choose not to inline, and in the case of runtime packages or DLLs, a function in another package cannot be inlined.
Skipping evaluation of an argument only occurs when the compiler is sure that there are no side effects associated with evaluation of the argument. For instance, if the argument involved a function call, the compiler will ensure that it is always evaluated.
To expand on point 2, consider the statement in your question:
Description := IfThen(Assigned(Widget), Widget.Description, 'No Widget');
Now, if Widget.Description is a field, or is a property with a getter that reads a field, then the compiler decides that evaluation has no side effects. This evaluation can safely be skipped.
On the other hand, if Widget.Description is a function, or property with a getter function, then the compiler determines that there may be side effects. And so it ensures that Widget.Description is evaluated exactly once.
So, armed with this knowledge, here are a couple of ways for your code to fail:
You move to runtime packages, or the compiler decides not to inline the function.
You change the Description property getter from a field getter to a function getter.
If it were me, I would not like to rely on this behaviour. But as I said right at the top, ultimately it is your decision.
Finally, the behaviour has been changed from XE7. All arguments to inline functions are evaluated exactly once. This is in keeping with other languages and means that observable behaviour is no longer affected by inlining decisions. I would regard the change in XE7 as a bug fix.
It already has been fixed - in XE7 and confirmed that this was supposed to be wrong behavior.
See https://quality.embarcadero.com/browse/RSP-11531

How to access 'self' in Console in Xcode 7.3

I am not able to get dictionary/array value in console while debugging.
It always show message while po dictionary/array like
error: warning: Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we
are in a generic context
Check the screenshot here
You can check the values of properties and variables using po [self variablename] in console window. This way you can easily access the variables.
Also you can check with other projects weather the problem is with xcode or in your project configurations.
You can also expand the collapsed value in debug area. if it's expanding then you can access values by simply using po variablename otherwise you need to use po [self variablename].
I'd the same issue and found out this solution. Changing this clang module debugging DEBUG to NO and RELEASE to YES will solve your issue.
Checkout this link below.
Accessing Self in LLDB
Please refer the following screen shot where i have printed the value of an array
This is a debugger bug (Yeah, imagine that!)
Simply restart XCode, and it shouldn't be a problem for you anymore :)
EDIT:
Psyche! I was thinking of something else.
You're creating a retain cycle, and as of now, the debugger classifies this specific retain cycle this way (As I said, a bug).
To fix this, create a weak copy of self:
__weak __typeof(self)weakSelf = self;
Then for the self that's giving you trouble:
Change self.object to weakSelf.object
Source: "self" not available in debugger on iOS 5.1

Check if UIBarButtonSystemItemPageCurl exists in iOS version

I am trying to check if UIBarButtonSystemItemPageCurl exists on a given device.
Note: UIBarButtonSystemItemPageCurl exists on iOS 4.0 and above. I am also targeting iOS 3.1.3. Don't worry about the targeting iOS 3 part.
Currently tried:
if (UIBarButtonSystemItemPageCurl != NULL)
and
if ((UIBarButtonSystemItemPageCurl) == TRUE)
to check existence of the constant (Is UIBarButtonSystemItemPageCurl considered a constant? It's a value of typedef enum UIBarButtonSystemIcon). These two methods are currently not working. Can someone provide guidance on checking the existence a value of in a struct (not the containing struct)? Thanks.
If you look in UIBarButtonItem.h, you'll find that UIBarButtonSystemItemPageCurl is defined conditionally using the preprocessor:
typedef NS_ENUM(NSInteger, UIBarButtonSystemItem) {
⋮
#if __IPHONE_4_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED
UIBarButtonSystemItemPageCurl,
#endif
};
…_MAX_ALLOWED is defined to the SDK version. Once the constant is defined, the constant always exists.
Comparing it against NULL is meaningless because this isn't a pointer. You are effectively comparing it against zero, and as it isn't the first thing in the enumeration, it isn't zero, so it is never NULL.
What it is is an integer. UIBarButtonSystemItemPageCurl is synonymous with 23, and the number 23 always exists, regardless of OS version.
So the question becomes “is UIBarButtonSystemItemPageCurl (a.k.a. 23) something that UIKit will recognize?”
One way to find that out would be to pass it to initWithBarButtonSystemItem:target:action: and see what happens. Hopefully, it will either return nil or throw an exception; either way, you can detect that and recover by doing whatever you need to do on iOS 3 devices.
Another way would be to ask the device for its systemVersion and compare it to #"4.0" in a way that understands version numbers. The Growl project has code for parsing and comparing version number strings. It's written for OS X, but should work with little to no modification on iOS.
I'd do the try-it-and-see approach first. Only if it silently fails (i.e., always returns a UIBarButtonItem, even on iOS 3, and the item you get on 3 just doesn't work) should you resort to comparing OS versions.

Any way to find more detail about WARNING: ID3D10Buffer::SetPrivateData: Existing private data of same name with different size found!

I'm encountering this error when I'm running my DirectX10 program in debug mode:
D3D10: WARNING: ID3D10Buffer::SetPrivateData: Existing private data of same name with different size found! [ STATE_SETTING WARNING #55: SETPRIVATEDATA_CHANGINGPARAMS ]
I'm trying to make the project highly OOP as a learning exercise, so there's a chance that this may be occurring, but is there a way to get some more details?
It appears this warning is raised by D3DX10CreateSprite, which is internally called by font->DrawText
You can ignore this warning, seems to be a bug in the Ms code :)
Direct3D11 doesn't have built-in text rendering anymore, so you won't encounter it in the future.
Since this is a D3D11 warning, you could always turn it off using ID3D11InfoQueue:
D3D11_MESSAGE_ID hide [] = {
D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS,
// Add more message IDs here as needed
};
D3D11_INFO_QUEUE_FILTER filter;
memset(&filter, 0, sizeof(filter));
filter.DenyList.NumIDs = _countof(hide);
filter.DenyList.pIDList = hide;
d3dInfoQueue->AddStorageFilterEntries(&filter);
See this page for more. I found your question while googling for the answer and had to search a bit more to find the above snippet, hopefully this will help someone :)
What other data are you looking for or interested in?
The warning is pretty clear about what is going on, but if you want to hunt down a bit more data, there may be a few things to try.
Try calling ID3D10Buffer::GetPrivateData with the same name or do some other check to see if there is data with that name already, and if so, what the contents are. Print your results to a file, output window, or console. This may be combined with breakpoints to see where the duplicate is occurring (break when there's already data).
You may (not positive) be able to set the D3D runtimes to debug mode and to break on warnings (not sure if it can do warnings or just errors). Debug your app in VS or your preferred debugger, and when the warning is shown, it will break and you can look at the parameters.
Go through your code and track down all calls to ID3D10Buffer::SetPrivateData and look to see if there are any obvious duplicates. If there are, work up the program flow and see why and what you can do about them (this may work best after you use one of the former methods to know where to start).
How are your data names set up, and what is the buffer used for? Examining one or both may lead you to a conflict somewhere.
You may also try unicorns, they've been known to help with this kind of problem.

Resources