Weird Compile Error In Swift When Using NSUserDefaults - ios

I've seen a number of questions about this, but I'm still confused as hell about what is happening.
I HATE blaming the language or compiler, but, with Swift, it's a definite possibility.
When I build and run in debug mode, all is right with the world.
However, when I compile in release mode, the compiler pukes with this error:
"Bitcast requires both operands to be pointer or neither"...Yadda, yadda
The offending line appears to be this one:
let lastURI:AnyObject? = NSUserDefaults.standardUserDefaults().valueForKey(s_currentURIKey)
It's right here, if you want to follow along in your textbook (It's an open-source project).
If I comment out this line (and the 7 lines below it), then the sun shines, and birds tweet happily. If I leave it in, then dark clouds and swarms of orcs spew forth from Mordor.
In order to make it fail, I simply run the profiler, which compiles in release mode.
Anyone have any experience with this kind of agita?
All the other versions of this issue tend to resolve to issues with specific Cocoa API calls. It's not clear to me whether or not the user is at fault.
I really want it to be my fault, which means there's something I can do about it.
If it isn't my fault, then I need to file a RADAR issue, and grow a long gray beard before I can test this app with a profiler.
It will be a while before it will be ready for release, but I like to test my apps in release mode very early on.

OK. Here's what I found out.
I had an array of tuples as a variable:
var arrayOfTuples:[(greeting: String, query: String)]! = []
I was appending to it using +=, and a single element array, like so:
arrayOfTuples += [(greeting: "HI", query: "HOWAYA")]
This worked and compiled fine in debug mode, but caused that strange error in release mode.
I fixed it it by replacing "+=" with ".append()", like so:
arrayOfTuples.append((greeting: "HI", query: "HOWAYA"))
Go figure. In any case, append was more appropriate, so good coding practice prevails.

Related

My code gives an "attempt to call a nil value" on the computer controlled seed analyzer in Minecraft

So I have spent a few hours looking for documentation on the item "Computer Controlled Seed Analyzer" with no current information that is useful. My goal is to set up a seed analyzer that will check for a plant next to the analyzer and analyze it.
My code:
local sides = require("sides")
if hasPlant(sides.left) and isAnalyzed() == false then
analyze(side.left)
end
From my logic, I believe the outcome should analyze the seed, but instead it gives an attempt to call a nil value (global hasPlant). From my research, sides were not defined at the time therefor I added the local line. What else would I be missing?
Two problems here:
The mods involved are currently buggy, so OpenComputers integration doesn't work at all. I opened pull request #1260 for AgriCraft and #31 for InfinityLib that will fix it. Until it's fixed, there's nothing you can do in-game to make it work. If you don't want to wait for official releases with the fixes, you can use my unofficial builds of AgriCraft and of InfinityLib, which I used to test my PRs and the below code.
The Lua code you're writing is wrong. I'm not sure where you got it from, but here's how you make it work:
if component.agricraft_peripheral.hasPlant("EAST") and component.agricraft_peripheral.isAnalyzed() == false then
component.agricraft_peripheral.analyze("EAST")
end
Of note:
The Agricraft API takes the strings DOWN, UP, NORTH, SOUTH, WEST, and EAST, rather than the numeric constants from side.
The functions provided by components in OpenComputers aren't globals; they're nested inside of component.
You may need local component = require("component"), so add it to the top if you get an error about it missing. (It works for me without it, but a bunch of documentation says you need it.)

Why does LambdaExpression.Compile() work on iOS (Xamarin)?

Since Xamarin.iOS doesn't support code generation at runtime, why do Compile() and DynamicInvoke() work as expected?
For example, the following code works fine:
var lambda = Expression.Lambda(
Expression.Add(
Expression.Constant(1),
Expression.Constant(2)
)
);
var f = lambda.Compile();
var result = f.DynamicInvoke();
// result==3 at this point
Is Xamarin evaluating the expression tree at runtime instead of emitting IL code?
On platforms that support code generation, Reflection.Emit-based LambdaCompiler is used.
If that's not available, the expression is interpreted using the interpreter. For example, there are classes that interpret Constant and Add.
The details of the Xamarin limitations are here.
You don't seem to be using anything in the Reflection.Emit namespace, which is the big no-no. Your code must still be AOT'd. Otherwise, I would imagine it would not work.
But there HAVE been examples of [native] developers thwarting the iOS static analysis tool and circumventing the dynamic code restriction. I tried to locate the article, but couldn't find it.
Anyway, I don't think your scenario exemplifies that. Your code example will still be AOT-compiled.
But you raise a really good question: at what time does the expression get evaluated?
EDIT:
Another SO answer on the same topic: What does Expression.Compile do on Monotouch?
There's also some good info on Expression.Compile() and "full AOT" here:
http://www.mono-project.com/docs/advanced/aot/
EDIT:
After reading some more, I think I know what's going on here. It's not that Expression.Compile() won't work...it's that when your iOS app bundle is subjected to the iOS static analysis tool when you submit it to the app store, it will not pass the analysis, because it is dynamically generating code. So, sure, you can use Expression.Compile(), but don't expect it to be accepted into the app store. But as mentioned by #svick, if you use the "full AOT" compile option, your Expression.Compile() will probably fail at runtime, or perhaps even fail compilation.

How to make Crash resistant ios apps

I'm now programming ios apps for a while. But still my apps crash regularly and it takes time to make them very stable. I find this very annoying.
So, are there any programming patterns regarding crash proof programming ios app?
Turn up the compiler warnings. Remove all warnings.
Run the static analyzer. Remove all warnings.
Run with GuardMalloc and/or Scribbling.
Remove all Leaks
Remove all Zombies
Write Unit Tests
Write a high level of live error detection (e.g. assertions)
Fix bugs before adding features.
Use source control and continuous integration.
Read. Improve.
1) Use ARC.
ARC has a small learning curve, and the big problem I read about on SO is that people instantiate objects but forget to assign the object to a strong ivar (or property), so the object mysteriously goes away. In any case the benefit is so compelling you should master this. When you do, most of all the memory management stuff you have to keep straight now goes away.
2) Build clean
You should never ever have warnings when you build. If you have a bunch, when a real problem comes up, it gets buried in the lines of cruft you got use to ignoring. Professional programmers build clean.
3) Use Analyze
Xcode/llvm has a phenomenal analyzer - use it - its under the Product menu item. Then clean up every single warning it gives you.
4) Use the right Configuration
I always have a Release (or Distribution) configuration, a ReleaseWithAsserts, and Debug. I only use Debug when using lldb, as the code is much bigger and it will execute differently than an optimized compile will. ReleaseWithAsserts is similar to Debug, but the Debug=1 preprocessor flag is removed, and the optimizer is set to -Os (the default for Release).
Finally, the Release/Distribution configuration has the following in the Preprocessing Macros:
NS_BLOCK_ASSERTIONS=1 NDEBUG
The first turns off all 'NSAssert()' lines, and the second all 'assert()' statements. This way no asserts are active in your shipped code
5) Use copious amounts of asserts.
Asserts are one of the best friends you can have as a programmer. I see sooooo many questions here that would never get written if programmers only would use them. The overhead is in typing them, since (in my usage) they are compiled away in the Release configuration.
Whenever you get an object from another source, assert its existence (ie:
MyObject *foo = [self someMethod];
assert(foo);
This is sooo easy to type, but will save you hours of debugging when a nil object causes problems thousands of instructions later. You can assert on class too:
MyObject *foo = [self someMethod];
assert([foo isMemberOfClass:[MyObject class]]);
This is particularly useful when you are pulling objects out of dictionaries.
You can put asserts at the start of methods, to verify that you received objects not nil too.
You can assert that some variable has a value:
assert(i>1 && i<5);
Again, in all but the Release/Distribution configuration, the assert is "live", but in that configuration they are compiled out.
NSAssert is similar - but you have to use different macros depending on the number of arguments.
NSAssert(foo, #"Foo was nil");
NSAssert1(foo, #"Foo was nil, and i=%d", i);
...
6) Use selective Logs to insure that things that should happen are
You can define your own Log macro, which gets compiled out for Release/Distribution. Add this to your pch file:
#ifndef NDEBUG
#define MYLog NSLog
#else
#define MYLog(format, ...)
#endif
This points up another point - you can use:
#ifndef NDEBUG
...
#endif
to block out a bit of code that does more complex checks - and its just active for your development builds, not for Release/Distribution.
You may already do these, but here's what I do:
Go to every screen in the app using the debugger/simulator, and select "Simulate Memory Warning". Go back to the previous screen. This causes existing UIView objects and variable assignments in viewDidLoad to be reassigned (which could result in bad pointer references).
Make sure to invalidate any running timers in the dealloc.
If an object A has made itself a delegate of object B, make sure to clear it in the dealloc for object A.
Make sure to clear any notification observers in the dealloc.

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.

Delphi error appeared suddenly on one machine: E2056 String literals may have at most 255 elements, how is it possible?

I was able to build one application up to this morning, then I don't know what happened as I try to build I have
[DCC Error] myunit.pas(1710): E2056 String literals may have at most 255 element`
Why this if this was working? (1710) was not edited in last month. I checked with a colleague project options and environement options one by one and they are the same. (the only difference is that i installed all Delphi updates, while he didn't anyway I didn't install them today).
moreover if I fix the above "erroor" by splitting the string in 2, doing something like
S := 'firstpart' + 'secondpart';
instead of
S := 'firstpartsecondpart';
// this is an example of course firstpartsecondpart
//is a string of more than 255 chars
I have another problem:
[DCC Error] myunit.pas(1797): E2283 Too many local constants. Use shorter procedures
Why this? I didn't change this procedure today. It is a long procedure indeed, but it used to compile up to this morning. I tried to split tjhe procedure in 2 and I was able to compile...
And Finally...
Breakpoints doesn't work anymore. If I try to set a breakpoint, after compiling and linking the RED cirlce of breaxpoint becomes green with an X, like when you try to debug a line of code that cannot be debugged.
I tried all, including rebooting and setting Debug Info to True in project options.
FINAL NOTE: It seems that for some reason some strange settings have been applied. I can't recall having done something strange. Recently I installed CnPack, but I could use it effectively for days. This problem started today.
Can anyone give me an hand? I am in real trouble, I lost half day and I still don't see a way out.
It seems you've changed the "Huge strings" project option. Did you add a {$H} to your code? Or did you fiddle with the project options? ("Compiler options/Huge strings" need to be checked to default to strings longer than 255 characters.)
The green breakpoint thingie means that this specific code is not compiled, thus it will not be called. Check if your code is calling this code, or perhaps it's looking at some other (pre-compiled?) unit.
My comments from below to complete the answer:If all breakpoints are green, it appears you have a problem setting the project options. If you remove the YourProject.dproj and YourProject.dproj.local files (Move somewhere else, don't delete) and then open the YourProject.dpr, your project should have the default options. Check if it works in that case. If not, move the old files back.The E2056 error is because strings inside Delphi code cannot be longer than 255 characters. Splitting it by including '+' in your string can fix this. See qc.embarcadero.com/wc/qcmain.aspx?d=71575 for why your collegue doesn't get this warning.

Resources