In Objective-C I would write:
#property (nonatomic, strong) NSMutableArray *privateArray;
if (!self.privateArray) {
// Populate the privateArray
}
Which checks that an array does not already exists before populating it. How could this be achieved in Swift?
I have tried implementing it by translating my Obj-C code but am given an Xcode error "Unary operator '!' can not be applied to an operand of type '[AnyObject]'"
Swift attempt:
private var privateArray: [AnyObject]?
if !privateArray {
// Populate the array
}
How would I check if the array exists before populating the array, in Swift?
Is it just as simple to use .isEmpty on the array?
Thanks in advance!
In Objective-C this is called lazy loading. You declare a property but only create the property the first time it is accessed.
The trap you have fallen into is thinking that Swift is just a different syntax around Objective-C.
In Swift you can have a lazy var...
You can declare it like this...
#lazy var someArray: [String] = {
return ["Hello", "World"]
}
This will do what you want.
As a side note. It's generally not a good idea to use AnyObject especially if you know the type of object the array will contain.
Also, by using this method you don't need the array to be optional and so can avoid the whole unwrapping thing.
You can read more about lazy properties by googling it. I found this and it looks quite good... http://mikebuss.com/2014/06/22/lazy-initialization-swift/
You should write:
if (privateArray == nil) {
// Populate the array
}
I have a custom class and I am trying to save an array within my class. In the encodeWithCoder method I use the encodeRootObject:theShotArray to save the data. What should I use for the initWithCoder method. There doesn't seem to be a decodeRootObject method. Is there a better way to save an array.
NSArray conforms to the NSCoding protocol, so you can say:
NSArray *rootArray = [[NSArray alloc] initWithCoder:myKeyedUnarchiver];
It may be a little confusing that NSArray's reference page doesn't specifically mention -initWithCoder:, but that's because that method is already described in the NSCoding protocol reference, and the NSArray reference page specifies NSCoding.
I have a property defined in a class like so:
#interface myClass
UIImageView *drawImage[4];
...
#property (nonatomic, retain) UIImageView **drawImage;
...
#synthesize drawImage; // This fails to compile
I have found similar questions on StackOverflow and elsewhere, but none that really address this issue. What is the most Objective-C kosher way to do this?
You can't; you have to change that retain to assign and handle memory management yourself; as you can't send -[retain] to an UIImageView ** (as it isn't an object.)
That is to say; you can't actually use #synthesize as that would lead to epic memory leaks with assign and doesn't work with retain or copy; what you need to do is to implement -drawImage and -setDrawImage: and write some actually accessor code.
But don't do that. Use an NSArray.
The most "kosher" way would be to create an NSArray of UIImageView objects, instead of a C-style array.
A problem you'll encounter is that functions can't return C-style arrays in C or Objective-C, and another problem you might face is that you can't assign a pointer type to an array type (which is what your synthesised setter may be trying to do). There are at least two solutions:
Use an NSArray rather than a C-style array. This is the cleanest route, especially since you only have to manage the memory of one object rather than four.
Wrap the C-style array into a struct. You can't return C-style arrays straight from functions but you can return a struct that has an array member (be aware that there is no retain/release going on).
typedef struct {
UIImage *image[4];
} ImageCollection;
...
#property (nonatomic, assign) ImageCollection drawImage;
...
#synthesize drawImage;
Something I see ppl define the variable like this:
b2World *_world;
b2Body *_body;
CCSprite *_ball;
instead of
b2World *world;
b2Body *body;
CCSprite *ball;
I familiar with the second one, but not the first one. So, I checked the Wikipedia about naming convention:
Names beginning with double underscore
or an underscore and a capital letter
are reserved for implementation
(compiler, standard library) and
should not be used (e.g. __reserved or
_Reserved).
So, is that any special meaning which is start with "_"?
The code I saw which using "_" to begin is here:
http://www.raywenderlich.com/457/intro-to-box2d-with-cocos2d-tutorial-bouncing-balls
The wiki page.
There's a long-standing convention among some Objective-C developers to prefix instance variables with an underscore. It can be helpful in several ways: one, it makes it easier to spot instance variables in a .m file; two, it relieves developers of having to come up with creative names for method parameters to avoid colliding with instance variable names; and three, as others have noted, it indicates that the instance variables are private, and therefore shouldn't be accessed willy nilly throughout the code.
In fact, I'd argue for avoiding accessing instance variables directly in methods other than accessors (getters and setters), -dealloc, and -init.... Not that you should never, ever use them anywhere else, but you should at least give it some thought before using an instance variable directly in other methods.
It's really really helpful, but most people don't know why, and that's a shame.
Apple uses underscores to separate the way other objects access a particular object's variables, and the way a particular object access its own variables.
Now this may sound a little bit strange, but imagine the following: You probably all recognize the following compiler warning
.h
#property (nonatomic, retain, readonly) UITableView *tableView;
.m
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self loadSomethingElseForTableView:tableView];
}
This will result in a compiler warning, because it does not know wether you reference to the local variable "tableView", or the instance variable.
Therefore, Apple recommends you to add the following to the top of your #implementation.
#synthesize tableView = _tableView;
Now, when you reference to _tableView, the compiler knows that you mean the instance variable, and not the local one.
Also, this makes it a lot easier to understand the Garbage Collection in Obj-C, and to prevent making common mistakes.
For example, when doing the following:
#property (nonatomic, retain, readonly) NSString *title;
- (id)initWithTitle:(NSString *)title {
if ((self = [super init])) {
self.title = title; // Is not possible, since it's read only.
title = title; // Is not possible, since it's the same (local) variable.
// Changing the method to initWithTitle:(NSString *)aTitle;
title = aTitle;
}
return self;
}
Now, since you do not use the default setter (actually, you can't, because it's read-only) you need to retain the variable yourself.
This is a lot easier to remember when you give every instance variable a prefix (so you know you need to retain it yourself).
So, basically, it's important to understand the difference between self.variable and (_)variable. (that is: self.variable maps to [self setVariable:...] and variable maps directly to your pointer.
Furthermore, when you add it as a private variable, like this:
#interface TSSomeObject : NSObject {
#private
NSString *_privateTitle;
}
#end
The underscore prefix isn't really necessary, unless you may encounter local variables that have the same name. Besides that, again, it's also an easy way to remind you that it's a local pointer and that you need to retain (and release) the variable when you assign it to your object.
What is wrong is to create a property with a underscore prefix, like this:
#property (nonatomic, retain) NSString *_title;
That's really wrong, and I'm not even gonna explain why ;)
So yes! You should really use underscore prefixes, it makes your code a lot easier to read, and to interpret by the compiler! In Xcode 4, Apple even added these #synthesizes to the default templates.
Usually they're used for variables that shouldn't be accessed outside the current file/module/namespace/whatever, in languages that don't support restricting access with something like a private keyword
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingIvarsAndTypes.html#//apple_ref/doc/uid/20001284-1001757
Both by convention and recommendation in the above document, you should prefix ivars with an underscore.
Admittedly, it is in reference to explicitly set ivars for properties.
But the usage is the same, to indicate the usage of an ivar wherever it is seen.
I am however open to the possibility, that in that context, the use of an underscore prefixed ivar could signal to the user that they are doing something wrong. Meanwhile a postfixed underscore could be used for pure ivars that are meant to be accessed directly.
This blog has some good thoughts from an experienced practitioner and it recommends using prefixed underscores.
http://blog.bignerdranch.com/463-a-motivation-for-ivar-decorations/
Wether you choose to use prefixed underscores to decorate your own ivars, there is at least some evidence that some kind of decoration will help you avoid bugs. And prefix'd underscores are the most common decoration.
Apple reserves names beginning with underscore for its own private ivars and methods. In Objective-C on any Apple platform, it is recommended that you do not prefix your identifiers with an underscore.
http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html
I have class1.m . I declared a method and written in it. Now i need to call it into another class. How can I make it? Can we use extern for it like we use for variables.
Thank you.
You should separate your declaration and definition, and place the declaration for class1 in class1.h. Then, you should include class1.h using #import "class1.h" in your source file for class2. Within class2, you can instantiate and use class1 as follows:
class1* instance_of_class1 = [[class1 alloc] init];
[class1 invokeMyMethod];
When you are done using your instance, be sure to decrement the reference count via release as in:
[instance_of_class1 release];
instance_of_class1 = nil;
I highly recommend reading Apple's Objective-C Programming Guide which will cover the fundamentals you need to know.