I am trying to adopt a SDK written in objective-c in a swift project. The objective-c way to initialize the SDK is as follows:
#implementation ViewController
nokeSDK *nokelock;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//INITIALIZE NOKE SDK
nokelock = [[nokeSDK alloc] init];
nokelock->cmd = [[nokecommand alloc] init];
I don't believe there is an equivalent to the arrow operator in swift, so is it possible to still initialize? I can't seem to find any info about his particular subject.
In Objective-C, a property is merely syntactic sugar for accessor methods; if, as is usually the case, these are a front for an instance variable, you can, with the right privacy access, bypass the accessor methods (or not have them in the first place) and get/set the instance variable directly. That's what your code is doing.
But Swift doesn't draw that distinction. A variable declared at the top level of a type declaration, in Swift, is a property; behind the scenes, a stored property has accessor methods, and you are passing through those automatically when you get/set the property. There is no separate instance variable to get/set.
To see what I mean, make a hybrid Swift / Objective-C app with class Thing whose interface looks like this:
#interface Thing : NSObject {
#public
NSString* s;
}
Now create the generated interface. You will see that, in Swift, s is nowhere to be seen.
Presumably, therefore, to rewrite your code, you'd need to turn cmd into a property, or at least provide a setter method. Otherwise, Swift will never be able to set the Objective-C cmd instance variable. Of course, if it is also up to you to rewrite nokeSDK in Swift, your problems are over, as you can now do whatever you like.
Related
I run into a fairly common scenario in Objective-C where I pass in a variable to an init method and then want to assign it to an instance variable of the same name. However I have not found a way to scope the variables to clarify which is the value from the message argument and which is the instance variable.
Say I have some class such as the following:
#interface MyObject
{
NSString *value;
}
- (id)initWithValue:(NSString *)value;
#end
In my implementation I want my init method to look something like this:
- (id)initWithValue:(NSString *)value
{
self = [super init];
if(self) {
self.value = value; // This will not work with instance variables
}
}
I know of three solutions:
Create a property, which allows calling self.value
Rename my instance variable, such as _value
Rename my init argument variable, such as initValue or argValue
I am not pleased with any of these solutions. Adding a property either makes the property publicly available on the interface or, if I use an extension, hides it from inheritors. I also do not like having different names for the variables or using an underscore, which perhaps comes from developing in other languages such as Java and C#.
Is there a way to disambiguate instance variables from message arguments? If not, is there a coding guideline in Cocoa for how to solve this problem? I like following style guidelines when appropriate.
Update
After thinking about how to do this in C, I came up with the solution of self->value. This works, but it produces a compiler warning that the Local declaration of 'value' hides instance variable. So this is not a satisfactory solution either since I have a zero-warning goal.
For setters (and by extension initializers), I believe the convention is to prefix the parameter name with new:
- (void)setCrunk:(Crunk *)newCrunk;
- (id)initWithCrunk:(Crunk *)newCrunk;
In general, I think the most common form I've seen is to call the parameter theCrunk, but Apple seems to recommend aCrunk.
And changing the name to "inValue" is not a good idea? What you have here - your 'solution' is complex, especially with the accessors, etc of Obj-C 2. Since self.value and inValue are different things, they need different names.
Note that you can use
-(void)method1:(NSString*)value;
in the header
and
-(void)method1:(NSString*)inValue;
in the .m file.
If you use only 1 the compiler will give you a warning.
You can combine 1 & 2 by using :
#synthesize value = _value;
If you want to hide your variable from the inheritors you can declare a empty named category and declare your property there.
For 3 you can use aValue for your argument.
Working on iPhone, after a lot of headache and memory problems I just realized from other examples that we do not need to necessarly create #properties for each instance variable we define in header file. And actually I found out ivars easy to just allocate and release it after I use anywhere in the class, for #properties I have to use autorealese or I have serious problems and becareful how I allocate..
For instance for objects below, #properties(retain/copy..) is not used in headers in many examples;
{
NSURLConnection *connection;
NSMutableData *xmlData;
NsMutableString *string
}
But for some strings or object types #properties is used, I know that when we set #property cocoa creates some setters getters which are handling the relasing and retaining of the objects. But seems like as for xmlData or connection instance variables we do not need that and they do their job like this.
Are there some reference guidelines I can keep in mind on deciding whether or not to create #property's or just use simple ivars?
My only problem when using properties is not becuase I am lazy to define it, but when I carefully allocate and init them in code, I have to use autorelase and dont feel like I have the control when to release reset and allocate it again, and it gives me one more thing to worry about while and when and how should I release, reset it. I find ivars I can alloc and release anytime once anywhere easily without worrying about anything..or I am missing other things here.
Tnx
There seem to still be some misconceptions flying around about properties.
that we do not need to necessarly create #properties for each instance variable we define in header file
Correct. You can use private instance variables directly in your implementation file. However, since synthesized properties come with free memory management, you might as well take advantage. My rule of thumb is to use the ivar directly until the first time I find myself writing:
[ivar release];
ivar = [newIvar retain];
As Sam says, there is already a potential bug there if iVar == newIVar. This is the point at which I switch from using ivars directly to creating a property. However, I put the declaration of the new property in a class extension in the implementation file. This means that the property is officially not part of the public interface (and will cause compiler warnings if used accidentally).
when we set #property cocoa creates some setters getters which are handling the relasing and retaining of the objects.
Actually, no. The #property just declares a property. In order to automatically generate the getter and setter, you need to #synthesize it. You could, alternatively write your own getters and setter which do not even have to reference a real ivar.
Technically, you should not use the property in the init or dealloc methods because a subclass might have overridden them or (in dealloc) you might set off a KVO notification.
From Sam's answer and comments
If you want a property regardless, you could use a private interface at the top of the implementation file
As I say above, private categories have sort of been obsoleted by class extensions (which is near enough the same thing but allows you to put the implementation of the methods in the main class implementation).
If you want the benefits of using dot notation shorthand
Some of us would argue that there are no benefits to dot notation. It's a gratuitous and needless pollution of the struct member syntax. However, dot notation has no relation to #property declarations. You can use dot notation for any accessors no matter how they were declared, provided they adhere to the pattern -foo and and -setFoo:
Create properties only for variables that need to be accessed from outside the class. Any class variables that are used internally need not have getters/setters defined.
Generally speaking an abundance of properties indicates high coupling and poor encapsulation. You should restrict what variables your class exposes in the interface.
EDITED to respond to comment:
Using properties over direct access may be preferred because it gives you easy memory management.. for example:
// interface
#property (retain) Object *someVar;
// implementation
self.someVar = otherVar;
is the same as
// implementation
if (_someVar != othervar)
{
[_someVar release]
_someVar = [otherVar retain];
}
However you should not needlessly expose vars in your interface because it opens the class up for people to use in the wrong way.
If you want a property regardless, you could use a private interface at the top of the implementation file
#interface TheClass(Private)
// private stuff
#end
First of all, let me say that Sam's answer is complete, IMO, and gives you clear guidelines (+1 from me).
My only problem when using properties is not becuase I am lazy to define it, but when I carefully allocate and init them in code, I have to use autorelase and dont feel like I have the control when to release reset and allocate it again, and it gives me one more thing to worry about while and when and how should I release, reset it. I find ivars I can alloc and release anytime once anywhere easily without worrying about anything..or I am missing other things here.
You should not worry about autorelease in the following idiom:
self.stringProperty = [[[NSString alloc] initWith...] autorelease];
because this is the way that things are meant to work;
EDIT: [the above statement has several parts:
the object is allocated and initialized (retain count is 1);
immediately, the allocated object is also autoreleased; this means that the object will be released automatically, (more or less) when the control flow gets back to the main loop;
in the very same statement, the allocated object is assigned to a retained property, self.stringProperty; this has the effect of (once again) incrementing the retain count;
So, it is true that autorelease adds some "ambiguity", because the object will be released at a time that you don't know precisely (but pretty soon anyway), but assigning to the retain property will increase the retain count so that you have full control over the lifetime of the object.]
If you don't like the autorelease you can always use a constructor method which gives you back an autoreleased object, when available:
self.stringProperty = [NSString stringWith...];
or assign directly to the ivar:
stringProperty = [[[NSString alloc] initWith...] autorelease];
because by accessing directly the ivar you are bypassing the setter and getter. Anyway, do the it only in this case (IMHO) to avoid ambiguities.
More in general, the autorelease glitch is the only drawback that using properties has over directly accessing the ivars. The rest are, IMO, only advantages that in many cases will save your life, and if not your life, a leak or a crash.
There is nothing you cannot do with directly accessing the ivars and taking care of when it is necessary to release before assigning, or not forgetting to set to nil after releasing, etc., but properties will do that easier for you, so my suggestion is simply use them and accept the autorelease shortcoming. It's only a matter of getting the basic "idioms" right.
It has long been custom to access ivars directly. That is, IMO, fine from inside the same class, although many properties are classes and then properties provide protection against retain/release issues.
IMO, it is, however, preferrable to encapsulate most ivars into properties, especially those that have retain/release semantics, but also those that need special handling, i.e. for which you write your own handlers, instead of using the synthesized ones. That way you can filter access to certain ivars, or even create properties that don't have any backing storage, and are just "aliases" to other properties, e.g. an Angle class that has a degrees property giving the angle in degrees, and a radians property denoting the same angle in radians (this is a simple conversion), or a property that must do a dictionary search to find its value, etc.
In Delphi, which was (AFAICT) one of the first languages with properties as language construct at all, it is customary to wrap ALL ivars in properties (but not all have to be public), and there are many such "unreal" (I am deliberately avoiding the term "virtual" here) properties, i.e. the ones that are only implemented in code, and not just getters and setters for an ivar.
Properties provide encapsulation, abstraction and a degree of protection against certain often made errors, and that is why they are to be preferred over direct access to ivars, IMO.
Addition
It doesn't make sense to declare and implement (either via #synthesize or with custom setters and getters) public properties for each ivar. Only expose publicly what others may need. Internal state can also be exposed to your own code via properties, but that should be done with a private or empty category in the implementation file. That way you get the automatic handling of retain/release and still don't expose them to the public.
What is the easiest way to create a global object. I have tried declaring the object outside the method with no luck.
#implementation UV_TouchpadViewController;
NSMutableString *string = [NSMutableString stringWithFormat:#"text"];
Very close -- you can't initialize a non-local variable with a non-const expression, and a method call is inherently non-const, even if it looks like it should be. So basically, change it to
NSMutableString *string;
but if it's only going to be used inside the implementation file (eg. other classes would only get at it through UV_TouchpadViewController, not get/set it directly (this is also the recommended pattern)), then qualify it as static, like so
static NSMutableString *string;
If on the other hand you do want to be able to access it directly from outside UV_TouchpadViewController, leave off the static, but add
extern NSMutableString *string;
to your header file (outside the class #interface), and whomever includes the header will be able to access it. (Note that you could instead just put NSMutableString *string; in your header file, however this is quickly becomes unclear)
Also, if you are trying to do this for a singleton class, (I can't think of a good reason to have a global mutable string -- you know they're not thread safe right?) I recommend reading Apple's docs on singletons first, where they suggest you use ivars, not global variables, even for singletons. However, UV_TouchpadViewController should not even be a singleton (if it is in any way a view controller), it should just have a single instance, if that's all you want.
If on the other hand you just want all UV_TouchpadViewControllers to have access to this one variable, note that across almost all languages this is considered a bad design pattern (globals are bad), and that you should instead stick it in, say, your app delegate (which is guaranteed to have a single globally accessible instance), where it can be an ivar+accessors, and generally considered a setting and (with a little extra code) persisted.
EDIT:
If you want to have a singleton that maintains global state, which I still recommend against -- you should create a class, like for instance ApplicationState, which handles all of the application's global state as a model object in the traditional model-view-controller pattern. I wont go into detail here because that would be highly redundant of a google search.
In your Application Delegate, somewhere, add an ivar ApplicationState *state, and a corresponding #property (and #synthesize in the implementation file).
There are few easier ways to shoot yourself in the foot than by using global variables.
You should never expose a dumb object like a string which has no access control to every object in the app. Any random piece of code anywhere in the app can change the mutable string leading to chaos as the app grows larger.
Usually when people want a global variable what they actually need is either the user defaults or a data model.
The user defaults (NSUserDefaults) is the preference persistence system that saves application state and user's settings both between launches and as the app runs. You can park small bits of data, such as strings, in the defaults and access them easily from anywhere in the app.
A data model is dedicated object that holds the applications data and manages access to it such that only the data model has final control. This makes it easy to tell what has changed the data and how. The data model can be a simple custom class or something elaborate such as core date. You can park the data model in the app delegate or create it as a singleton as the other answered have explained.
I have been using the Apple API for years and I have never needed to use a real global variable. If you think you need one, you probably have misunderstood something about application design in the Apple API. You might want to post a question explaining what you're trying to do with a global variable and what the best strategy should be for doing it without the dangers of using a global variable.
Do you need it for each instance of the class? If so, you should make it an Instance variable. Put
NSMutableString *string;
In your header
And then you can set it in any method in your class.
If this isn't what you meant, update your question or comment.
You can achieve that by implementing getter and setters in the delegate class.
In delegate .h file
Include UIApplication delegate
#interface DevAppDelegate : NSObject <UIApplicationDelegate>
NSString * currentTitle;
- (void) setCurrentTitle:(NSString *) currentTitle;
- (NSString *) getCurrentTitle;
In Delegate implementation class .m
-(void) setCurrentLink:(NSString *) storydata{
currentLink = storydata;
}
-(NSString *) getCurrentLink{
if ( currentLink == nil ) {
currentLink = #"Display StoryLink";
}
return currentLink;
}
So the variable you to assess is set in the currentlink string by setters method and class where you want the string ,just use the getter method.
AppDelegate *del=(AppDelegate *)[[UIApplication sharedApplication]delegate];
TO set:
[del setCurrentLink];
TO Get:
NSString *value=[del getCurrentLink];
All the best
Add:
NSMutableString *globalString = nil;
to any .m file of any object. The nil initialization adds a little safety, since nil objects can be "safely" messaged without outright crashing the app.
Add:
extern NSMutableString *globalString;
to the headers of any other objects that needs to access this global.
Add:
if (globalString == nil) {
globalString = [ [ NSMutableString stringWithFormat:#"text"] retain ];
}
to the init of any class(es) that could be the very first to touch this global, or to some init that happens even earlier.
Globals are a less verbose form of singleton, but with no access restriction or tracking. Use with caution.
actually as per my r&d i got that by use of extern we have to create an instance but the final thing is to #define your variable and can access any where you want without any creating of instance and other thing just directly use variable by its name....
Whats the difference between a property and an instance variable in Objective-C. I need to understand this in OOP terms. Is a property declaration just a convenience wrapper (with #synthesize in the implementation) for accessing instance variables?
thanks,
codecowboy.
Properties and ivars are two completely different things.
And instance variable is a variable stored inside the object, so each instance has its own. It is referenced by pointer addition relative to the object pointer/self (slightly indirected for the modern runtime, but functionally equivalent). ivars are generally internal to a class, and by default can only be accessed by the class and its descendents (#protected). Within methods they are available with no qualification, otherwise they can (but rarely are, ad usuaually should not) be accessed via indirection, eg obj->ivar.
A property defines a getter and setter (the setter is optional) interface. That's all it does. It defines two public methods:
- (TYPE) propname;
- (void) setPropname: (TYPE) newPropname;
These are defined as methods exactly as if you declared them like that, no more, no less. These methods are called either with the normal syntax ([obj propname] and [obj setPropname:n] or using the modern dot notation (obj.propname or obj.propname = n). These two options are syntactically different only, they behave identically, and you can use dot notation whether the methods are declared with #property or declared manually as above.
You must then implement the methods in the implementation, either by writing the methods yourself, by using #synthesize, or by handling the missing method dynamically.
Properties may be backed by an ivar (named the same or named differently (my preference to avoid confusion)), or they may not. They may store their value elsewhere, or they may calculate it from other data.
For example, you might have:
#property (nonatomic, readonly) NSString* fullname;
and then implement - (NSString*) fullname to return the concatenation of firstname and lastname.
I think you are pretty much there. The #property and #synthesize make the accessor declarations and implementation for the already declared ivar. You have various attributes you can define on the #property too giving you control over how it is generated to make it appropriate for the ivar
Have a look at "Objective C 2.0 Declared Properties"
The difference between Property and Instance ivar is, the variable which make as Property that can be visible in another Class whereas for accessing the iVar or instance you need to create the Object of that class and then you can access.
and With use of #synthesize compiler will generate the setter and getter for that property.
-(TYPE)name;-getter Method
-(void)setName:(TYPE)aName; setter Method
I was looking at some sample code on Jeff LaMarche's excellent blog when I came across the following:
- (void)applicationDidFinishLaunching:(UIApplication*)application
{
CGRect rect = [[UIScreen mainScreen] bounds];
window = [[UIWindow alloc] initWithFrame:rect];
GLViewController *theController = [[GLViewController alloc] init];
self.controller = theController;
[theController release];
// ...
}
In the .h, we see that "window" and "controller" are ivars declared as so:
#interface OpenGLTestAppDelegate : NSObject
{
UIWindow *window;
GLViewController *controller;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet GLViewController *controller;
#end
My question is: Why are "window" and "controller" assigned in different ways?
I think I understand why each kind of assignment works (keeping track of retain count), but why are they assigned in different ways? Specifically, why isn't controller assigned in the same way window is with a single line like so without going through the setter:
controller = [[GLViewController alloc] init];
In general, when would you use the single line method and when would you use the multiple line method?
Thanks.
Does he create a custom setter for the controller instance variable?
If so, there may be code which is called when the controller variable is changed through the setter. Merely setting the controller variable with:
controller = [[GLViewController alloc] init];
would not invoke the setter method; however, assigning the newly allocated object to a local variable then setting it with:
self.controller = theController;
would invoke the setter method since it is a shorthand way of writing:
[self setController:theController];
and the extra code in the setter would be executed. This is commonly where you would expect the differentiation between the two methods.
Edit:
Evidently, after taking a look at the code, he doesn't implement a custom setter method, however the method that he has used is still most commonly used when a custom setter method would be implemented.
My guess at the reason behind the extra code would be that he plans to release the variable after allocation, and if assigned to a local variable, he can call the setter method with the local variable and then call release on the local variable afterwards. This would be overall more readable than using
[[self controller] release]
However, it is an odd way to do it, as the synthesized implementation of the setter will retain the instance variable, yet he then releases it once it has been set to the instance variable, and as the release call cancels out the retain call, it would make more sense to set the variable using the one-line method.
The extra code seems to be just because he specifically wants to use the property (setter method). In his implementation (GLView.m), -setController also sets a boolean ivar based on whether the controller responds to (implements) the -setupView: method.
Even so, it would seem that a one-line solution would work just as well:
self.controller = [[[GLViewController alloc] init] autorelease];
The same line as an explicit message send (without dot syntax) works as well:
[self setController:[[[GLViewController alloc] init] autorelease]];
Either approach will leave the new controller with the proper retain count, and still uses the setter property as desired.
(Note: The code in question is linked at the end of this blog post.)
Edit:
Sorry for any confusion. The code has a "GLViewController *controller" ivar and property both in ___PROJECTNAMEASIDENTIFIER___AppDelegate.m and GLView.m, and I was looking at the latter. (In the former, the setter is indeed synthesized, and it will retain the controller. On lines 77-81, you can see the code I mentioned, and he doesn't actually retain the controller — only the AppDelegate retains it.)
In the app delegate code, the synthesized setter will retain the GLViewController, so my one-line replacement advice still stands. One can argue both ways about readability, but for those who understand the retain-release idiom well, I would suggest that the one-line version is much more readable. It communicates the intent succinctly, and even provides an implicit hint that the setter will retain the controller. The extra local variable is really just unnecessary fluff.
As Quinn pointed out, the assignment to the controller ivar may be written in one line using autorelease method. The reason to use more verbose version is exactly to avoid autorelease and use manual release instead. This is due to Apple recommendation to minimize the use of autorelease pools on iPhone. So you must store the reference to the newly allocated object in a local variable to release it after a call to setter.
Considering the question when to use direct assignment to an instance variable (as in the case of window ivar) and when to use a setter method (as in the case of controller ivar), it is mostly a question of style, but you better be consistent.
There are two styles of ivar setting:
Always use direct assignment to an ivar. Switch to setter methods only for ivars for which setter must perform some additional work beside assignment.
Always use setter methods for all ivars.
Personally, I think that use of the second style results in more consistent and maintainable code. If some day you realize that your setter must perform more work you should change only the setter, while when using the first style you also should change all occurrences of direct assignment to the setter call.
Just found the good discussion of the issue in another thread: instance variable/ method argument naming in Objective C.