I've seen code examples of variables and constants created outside classes as a way to avoid hard-coding.
Are they a good practice in terms of memory allocation?
For example:
private let cellId = "myCellId"
class ViewController : UIViewController {
...
let cell = tableView.dequeueReusableCellWithIdentifier(cellId)
...
}
When are these constants/variables allocated/deallocated in an iOS application?
Top level global variables like this are lazily initialised. Also, they are implicitly allocated within a dispatch_once so they are thread safe.
The lazy initializer for a global variable (also for static members of structs and enums) is run the first time that global is accessed, and is launched as dispatch_once to make sure that the initialization is atomic. This enables a cool way to use dispatch_once in your code: just declare a global variable with an initializer and mark it private.
Reference: Swift blog
In general, Abizern is correct. However, constant strings are a bit of special case. They're never allocated. They live in your binary image, which is memory mapped, which is about as close to "free" as you can get. Since structs are exactly their contents (i.e. there's no header on a struct), your string costs exactly 9 bytes in the binary (the characters plus a trailing 0). It is never allocated; it just is.
Since cellId is let, the compiler can replace references to it with the actual memory location in the binary that holds the data. There's not even a need for a pointer for cellId itself.
Related
It is hard to find a good heading for this, but i think my problem comes clear if i post a small code snipped:
SomeObject instance = SomeObject(importantParameter);
// -> "instance" is now a reference to the instance somewhere in RAM
instance = SomeObject(anotherImportantParameter);
// -> "instance" is now a reference to a different instance somewhere in RAM
My question is now, is the used RAM that was allocated at the first construction reused at the second construction? Or is the RAM of the first instance marked as unused for the garbage collector and the second construction is done with a completely new instance with a different portion of RAM?
If the first is true, what with this:
while(true) {
final SomeObject instance = SomeObject(importantParameter);
}
Will then, each time the while is repeated, the RAM be reused?
It's unspecified. The answer is a resounding "maybe".
The language specification never says what happens to unreachable objects, since it's unobservable to the program. (That's what being unreachable means).
In practice, the native Dart implementation uses a generational garbage collector.
The default behavior would be to allocate a new object in "new-space" and overwrite the reference to the previous object. That makes the previous object unreachable (as long as you haven't store other references to it), and it can therefore be garbage collected. If you really go through objects quickly, that will be cheap, since the unreachable object is completely ignored on the next new-space garbage collection.
Allocating a lot of short-lived objects still has an overhead since it causes new-space GC to happen more often, even if the individual objects don't themselves cost anything.
There is also a number of optimization that may change this behavior.
If your object is sufficiently simple and the compiler can see that no reference to it ever escapes, or is used in an identical check, or ... any other number of relevant restrictions, then it might "allocation sink" the object. That means it never actually allocates the object, it just stores the contents somewhere, perhaps even on the stack, and it also inlines the methods so they refer to the data directly instead of going through a this pointer.
In that case, your code may actually reuse the memory of the previous object, because the compiler recognizes that it can.
Do not try to predict whether an optimization like this happens. The requirements can change at any time. Just write code that is correct and not unnecessarily complex, then the compiler will do its best to optimize in all the ways that it can.
I have been looking at Swift the last couple of days and it looks good, I am confused on a point though even after review of the guide Apple published.
I understand that memory management in Swift uses ARC and therefore quite safe, however in situations where I'd like more fine grained control of object creation and destruction I'm slightly confused.
Take these two simple examples:
In ObjC, when you'd (for example) like a UIViewController you intend to push to stay around for the lifetime of your app and only be created once (say because it's expensive to create), you'd make it a property and then wrap it's Alloc Init like this:
if (!self.myProperty)
{
self.myProperty = [[MyObj alloc] init];
}
This way it only creates once, keeps state and the same object instance can be reused indefinitely, yielding known object references, and good performance not having to recreate each time the viewController goes out of scope.
Another example of this is with NSMutableString, vs Swifts String.
You can set an NSMutableString's string many times and it will keep the same object reference, however this doesn't seem to be the case with a Swift String when changing it.
This may just be 'deprecated thinking in Objective C' but is there a best practice with regard to keeping around expensive objects or to keep state (same object) for certain objects during the lifetime of their usage.
I think what you're looking for is a "Lazy stored property":
The example in the swift docs is:
class DataManager {
#lazy var importer = DataImporter()
var data = String[]()
// the DataManager class would provide data management functionality here
}
and it says about #lazy:
A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the #lazy attribute before its declaration.
The comment about NSMutableString is a little different, you can continue to use NSMutableString in your swift code, but Apple are encouraging developers to use the Swift built-in types whenever possible :)
see the "String Mutability" section in the swift docs
This question already has answers here:
What makes a static variable initialize only once?
(4 answers)
Singleton objective c clarification
(5 answers)
Closed 8 years ago.
The code below is from the Big Nerd Ranch iOS programming book, 3rd edition. It's a class method that checks whether the singleton class BNRItemStore has been instantiated. If it has, it returns the singleton instance, and if it hasn't it creates it. The part I don't understand is the static variable. I know that static variables keep state, however, wouldn't calling the method a second time reset the *sharedStore back to nil? i.e. isn't this an assignment which would erase the creation of the singleton instance once the method was called again?
static BNRItemStore *sharedStore = nil;
Method
+(BNRItemStore *)sharedStore
{
static BNRItemStore *sharedStore = nil;
if (!sharedStore)
sharedStore = [[ super allocWithZone:nil ] init ];
return sharedStore;
}
Unfortunately, C terminology is really confusing. static has nothing to do with singletons, standing still, not changing, or anything like that. It has to do with the level at which storage takes place.
A variable declared inside a method/function is normally an automatic variable, meaning that it goes out of existence when the scope ends (i.e. execution reaches the end of the surrounding curly braces). A variable declared static, however, is stored at the level of the file that holds the code; once the file is loaded, this variable persists, even though it is declared inside a method/function.
Now we come to the question of how you will know whether this variable has ever been assigned a value, because you only want to assign it once. In theory, a static variable has a zero value when it is initially declared. Thus, if you said merely
static BNRItemStore *sharedStore;
...the code might work, because zero is nil for an instance, so we could test against nil and assign a value only in that case. However, it does no harm to make assurance double sure. Thus, we typically initialize the variable to nil when we declare it, just so we can be sure our nil test will work the first time.
That initializer, as you've already been told, will then take effect only once, because after that, the value persists and so the variable never needs to be initialized again (and never is).
The code is fine, the initialiser only gets called the first time.
Static initializers are guaranteed by the language specification to only be executed one time, (and that's actually done at application start time, not as a part of function execution) so the static variable will only be nil the first time the function is executed.
I just created a new class in my project, subclass of UITableViewController and noticed that in the method tableView:cellForRowAtIndexPath: template, Apple still provide a static local NSString to use as a cell identifier.
I know that for static global/local variable we need to assign nil cause it's considered as strong.
So I asked myself the question : Where should I assign nil to static global variable ?
And static global variable ?
Thanks for the answers guys
A short answer to the "where should static global variables be released" is "nowhere".
Long answer goes like this: when you make a variable static or global, you want it to exist regardless of any instances of your classes coming into existence or being released. Simply speaking, you want your statics to always be there for you. Therefore, the only reason to release them would be if your program is about to exit. But if your program is exiting anyway, you might as well let the operating system handle the cleanup for you, and forget about releasing your global and static variables.
Note, however, that the use of static and global variables should be an exception, not a norm. You use them for a good reason, and exercise your best judgement to decide what should be static. Moreover, you should avoid referencing collections of non-static variables from static ones through a strong reference, because otherwise you may create hard-to-find memory leaks.
There is nothing wrong with a static local for the NSString used as your cell identifier: it takes very little memory, and it does not grow, so it's not a big deal that it is not released at the end of your program's run.
You don't need to do it, it will never be released and its ok since it is a global.
In ARC will be treated as strong for default and its lifetime it is equal to the application lifetime.
Static strings are a special case, and don't need to be released.
static variable, means it holds a strong reference to the object it points to.
static MyClass *var;
var = [MyClass instance];
Now var always holds strong reference to the above allocated object.so it will never be removed from memory.
But after some condition you no longer need that object,then simply
var =nil would work.
because now var points to nil and no longer points to created object.so that object will be deleted from memory.
I know this could be a noob question but I am a bit stucked here. I usualy makes the following to access app data in different ViewControllers: First I declare a global.h module like this
global.h
typedef struct {
NSString *appName
NSString *appVersion;
bool mode;
} structApp;
extern structApp app;
After that I declare in MainViewController.h the struct so that I can access data
#implementation ViewController
structApp app;
- (void)viewDidLoad
{
app.appVersion = #"v1.02";
}
#end
And then I include "global.h" in every ViewController.h
This way I can access globally. As far I can see this is a good implementation and I have used it in more than 20 apps. Problem starts when this struct grows in size. In those cases I see corrupted memory, nil variables that were previously loaded with data, etc.
There is a better way of making data available in all ViewController? Please give me some examples if you can.
You have two options
Use a singleton class - Refer Objective C Singleton
Declare properties in App delegate - Refer SO
You can access the app delegate from any class using:
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
As you were using extern in your structure, any object updating the same value.
In OOPS, global variables are never said Good, so you need to use a singleton pattern.
Create a singleton/shared class having all those stuffs in your structure and use it.
You should deal with struct only if you deal with primitive data (if you are in a OOP way).
app.appVersion = #"v1.02";
Make your struct pointing on dangling pointer, since you are pointing a data in a function scope (app.appVersion is only holding the pointer, not the data). So you must retain all those object values in order to make it content safe, but i must admit it is still a Q&D approach.
If you need global access to data, you can use a singleton, only if you really need strong encapsulation and control to data.
How to make a singleton
What should my Objective-C singleton look like?
You can use macro too, that way you'll can use constants string without worrying data persistency, since they will always be available into the scope you are dealing with.
If you only want to read the data and you dont need any complex data structure you can also use a settings file like
Settings.h
#define appName #"blabla"
#define appVersion #"1.01"
#define mode 1
In General using struct should work fine. There is nothing wrong with using them. If you observe weird values caused by overlapping memory or illegal re-use of it or so then your problem is somewhere else but not in using structs in principle. The extern statement could lead to such an issue.
A class is not much more than a struct too, from a memory usage perspective. If I were you I would design a class with properties where ever you have members when using a struct. And make use of them in pretty the same way.
For "global variables" I apply a singleton pattern. That is basically a class with a class method (the leading + instead of -) that makes the one and only instance of the class available. Within that method I check if the class (a class internal static reference to the same class) is already available (!= nil) and instantiate it. Sometimes I use the initialize method for that. Initialize is an objective-c typical thing. It is called only once for each class, even subclassed ones, when or before the class is used for the first time. A very good place for instantiating class variables as singletons but not portable to other programming languages.