I'm going through an old code base and fixing issues that pop up with xCode's static analyzer. The issue that shows is that the value is never read and basically what is happening in this method is that it's taking a string that should be a number and casting it to an int. Here is the line in question though:
if (len50 == CANNOT_CALCULATE)
{
len50 = 0;
strLen50 = #"";
}
Cannot_Calculate is a macro for a certain int that means it wasn't casted correctly and there's an else statement that does stuff with the int it it was casted correctly. The objects len50 and strLen50 aren't used at all after this if check, hence the reason of the warning from the analyzer.
My question is if this line is necessary? Does setting a int to 0 or string to an empty string save on memory? If it does then the owner of the codebase will want it in, but it doesn't then I might as well get rid or it.
That be some weird code all the way around.
1) No, setting a variable to a value does not impact memory one way or another. If the value is never read, it is a wasted line of code (that the compiler will likely optimize away anyway).
2) !"" would be weird for setting a boolean value.
I'd be highly suspect of the rest of the codebase, having just read that. (Having been a consultant on many projects, suspect code is oft a way of life.)
Related
After merging master to my working branch I got compiler error on the line, which wasn't be changed. The error looks like
id test;
[test count];
Multiple methods named 'count' found with mismatched result.
At first it looks clear, because compiler doesn't know which concrete type the "test" variable is. But I don't understand why it worked before.
If I create a new file this line works, assuming that is a NSArray's method. Why compiler doesn't show error in this case?
While showing error message, there is several possible receivers of count method are shown. (NSArray, NSDictionary, NSSet) Does it search all classes that can receive that message and show error if there are multiple?
I noticed that error occurs when I import "-Swift.h" file. How it depends?
Compiler doesn't cast or check your id type. It just provides you all possible selectors. You said that this issue connected with importing "-Swift.h" file. In this case check you Swift code, probably you have count function visible for Objective C which returns something else than Int.
Also, you can check the issue in Issue navigator, select it and it will show all count calls visible in Objective C. Check them all, most of them will return NSUInteger, but there should be one that returns something else, for example:
SWIFT_CLASS("_TtC3dev19YourClass")
#interface YourClass : NSObject
- (int32_t)count SWIFT_WARN_UNUSED_RESULT;
#end
Objective-C doesn't need to know the type of the receiver. At run-time, all objects are just id, and everything is dynamically dispatched. So any message can be sent to any object, no matter its type. (At run-time, objects are free to decide what to do with messages they don't understand. The most common thing to do is raise an exception and crash, but there are many kinds of objects that can handle arbitrary messages that don't map directly to method calls.)
There is a couple of technical details, however, that complicate this.
The ABI (application binary interface) defines different mechanisms for returning certain primitive types. As long as the value is "a word-sized integer," then it doesn't matter (this includes things like NSInteger and all pointers, which means by extension all objects). But on some processors, floats are returned in different registers than integers, and structs (like CGRect) might be returned in a variety of ways depending on their size. In order to write the necessary assembly language, the compiler has to know what kind of return value it will be.
ARC has added additional wrinkles that require that the compiler know a more about the type of the parameters (specifically whether they're objects or primitives), and whether there are any memory-management attributes that have to be considered.
The compiler doesn't really care what "real" type test is, as long as it can figure out the types and attributes of -count. So when dealing with an id value, it looks through every known selector it can see (i.e. every one defined in an included header or the current .m). It's fine if there are many of them on different classes, as long as they all agree. But if it can't find the selector at all, or if some of the interfaces disagree, then it can't compile the line of code.
As lobstah notes, you likely have a type somewhere in your Swift code that has an #objc method called count() or an #objc property named count that returns something other than Int (which maps to NSInteger, and so match the usual signature of -count). You'll need to fix that method, or you'll need to hide it from ObjC (for example, by adding #nonobjc).
Or much better: get rid of the id, and use its actual type. id is generally a bad idea in Cocoa, and is especially a bad idea if you're calling methods on it, since the compiler can't check that the object will respond and you may crash.
After updating to XCode 6.3, compiler started giving this warning.
Comparison of address of 'myObject' not equal to null pointer is always true.
Here is my piece of code,
Scratching my head with it, but didn't find any solution or workaround to get rid of this warning.
My question is linked with question over here. But, it can't be solved using answer discussed.
Any help will be welcomed :)
Correct way of checking the pointer is
if (anotherInView != nil) {
}
You are comparing address of a variable with the NULL. Every variable has an address you can't have a variable whose address is NULL, you can have a variable whose value is NULL
Also anotherRect != NULL is again not valid. anotherRect will always have a value as it's a struct
There are four mistakes here. The first two are that you aren't setting any initial values for the CGRect and UIView variables, so there's no way to detect a failure. Try setting the CGRect to a zero-width, zero-height rect initially if you think that is useful, and set the UIView to nil.
The third and fourth mistakes are that the address of a local variable is never NULL. (Note that this is not true for global variables in libraries, as I mentioned in another comment—the address of an NSString pointer constant might be NULL if the symbol didn't exist on the version of the OS you're running—but for local variables, you're guaranteed an address up to the point where your stack overflows and your app crashes.)
I'm also puzzled by why you're calling a delegate method yourself. Normally, the OS itself calls those methods, so calling them yourself is somewhat atypical usage. To be fair, I've done it on occasion when a delegate method performs a computation that I need somewhere else in the code, and I've also done it when implementing delegates that call other delegates, but in the context of this question, it seemed like a potential mistake.
For the first instruction, a changed to :
if (!CGRectIsNull(anotherRect)) {
}
I have a need to ensure the user-inputed string in a UITextField is cleared from memory immediately after it has been used. If I set field.text = #"" or nil and let it go out of scope it should ge gone but I am not sure if it is guaranteed to be released immediately and even if it is, I dont think the OS actually clears the data, it seems likely it is just marked as unused and the data in it is still there until overwritten by something else.
The .text property of the field is a normal NSString and I have looked around for ways to get a useable pointer to its contents using the various CFString / CString methods but none of them work. For example CFStringGetCharactersPtr and CFStringGetCStringPtr both either return const-pointers which cant be written to, or often NULL (the docs say it may return null "if the internal storage of the String does not allow this to be returned efficiently") and from my testing it always returns NULL.
Is there anyway to do this?
answering my own question to be clear:
I got a reply from an apple employee at the devforums and he confirms it is pretty much impossible. His suggestion was to do everything yourself based on UITextInput and not use NSString or UITextField at all.
Since the last update of Xcode (to v4.6) I've got a bunch of the following warnings:
"Direct comparison of string a literal has undefined behavior"
This is when a NSString property is compared with another string by this way:
if ([self.myString isEqualToString:#"Compare Me"]) { ...
Originally I compared with self.myString == #"Compare Me" but there are the same warnings. Xcode suggests to use isEqual: instead.
I wonder why I should do this. Other comparisons still work, e.g.:
if ([segue.identifier isEqualToString:#"nextScreen"]) { // => NO WARNING HERE
Edit: OK, for anyone who doesn't believe/downvoters, see this screenshot:
Sometimes Xcode gets confused and shows old warnings. I suspect it is showing an old warning for use of ==. Clean the build, go to the organiser window and delete the derived data for this project, then restart Xcode.
Basically (according to this other stackoverflow answer, you should switch any of your == string comparisons to use isEqual or isEqualToString.
To make it easier, I found this post on bignerdranch's blog that said there is no difference (in the observable human world) between isEqual and isEqualToString, so I personally use isEqual.
When you use "==", it should, in theory (like in C/C++) compare the pointers, not the value of the objects.
Fact is obj-c (and compiler I guess) will understand what you really want and transform this in isEqualToString. But to be "safe", it's better to use the good method to compare two strings, two numbers etc.
Please help me, what am I doing wrong.
I use BubbleCell and BubbleElement from the examples.
For unknown reasons, the application sometimes crashes in native code.
I try out a little bit to correct the situation if I do not use DequeueReusableCell, and always create a new BubbleCell.
Also, the problem disappears if the constructor BubbleElement to pass a string constant as the caption, not the object field.
Stacktrace: http://pastebin.com/KAYzpHDk
The problem is deeper than it seems.
Your suggestion doesn't help, the application still crashes.
I made a separate project, leaving it a minimum of code necessary to show the problem.
The problem is somehow related to System.Json... maybe.
Here is an archive of the project:
https://dl.dropbox.com/u/63074515/BubbleNativeCrash.zip
The sequence of actions:
1) open the project
2) compile and run the emulator without debugging (configuration Debug|iPhoneSimulator)
3) click horse1 in the first view
4) in the list that appears, scroll whole items a few times up and down
5) in my case at this stage we crash... (stack trace: http://pastebin.com/KAYzpHDk)
If not immediately fail, you can return to the contact list, and vice versa, or even once a few times.
How quickly will fail depends on the number of messages in the chat.
Now the fun part.
The problem disappears completely (or I can not repeat it in a reasonable time) if in ChatViewController.cs comment the line 406 and uncomment line 407:
// string messageText = msg.MessageText ?? string.Empty;
string messageText = "Hello, World!!!";
That is, make a constant string passed into BubbleElement constructor.
After that, the problem does not repeat, I think.
I tried to leave everything as is, but remove the work with the Json - the problem disappears.
The problem in only when BubbleElement takes a string read from the JsonValue (IM\IMMessage.cs at line 36).
Even if there is, in IMMessage.cs, to set a constant string for MessageText - the problem disappears.
What am I doing wrong? :)
p.s. Sorry for my english... it powered by google translate.
You do not keep any reference to the managed instance you return from GetCell. As such the GC can (and will) collect the managed instance once the method returns while the native instance will continue to live (since it's referenced inside iOS).
This works fine when you use UITableViewCell since all the state is kept inside the native instance. However this is not the case if you inherit from it and add your own managed fields. In such cases you won't be able to access the managed state since it won't exists (the instance you'll have won't be the one you created).
The easy way to solve this is to keep a reference to the BubbleCell you create, e.g. in a list, so the GC won't collect them.
static List<BubbleCell> cell_cache = new List<BubbleCell> ();
public override UITableViewCell GetCell(UITableView tableView)
{
var cell = tableView.DequeueReusableCell(isLeft ? BubbleCell.KeyLeft : BubbleCell.KeyRight) as BubbleCell;
if (cell == null) {
cell = new BubbleCell(isLeft);
cells_cache.Add (cell);
}
cell.Update(Caption);
return cell;
}
Do not forget to clear the list once the cells are not needed anymore (e.g. when closing the UITableView).
UPDATE FROM EXTRA INFORMATION
The cell_cache must be static or it won't help (my mistake, fixed above) to keep references alive. But, as you found out, it's not the fix for this case (source shows the cells can be reused).
OTOH the issue is not related to using JSON. Using the same string messages (e.g. from an array) results in the same crash. That's a bit weird and I'll investgate this further...
FINAL UPDATE
It turns out the calls to CreateResizableImage can hit an iOS bug. The workaround is to use the older StretchableImage API. The issue was (re)submitted to Apple.