When would you declare variables in package instead of as properties? - ios

I have noticed in many of the header documentation files in the Apple framework that define variables within brackets directly following the interface definitions like the variables a and b below:
#interface MyView : UIView {
#package
int a;
UIView b;
}
Normally I have just been declaring all variables as properties for the convenience of the synthesized methods. Can anyone tell me when it would be more efficient or more proper to declare variables under #package instead of as #properties?

#package is an access specifier, similar to how it works in Java (it allows access from any code at the same package level). But since the . syntax with Objective C objects works with properties, and not direct member access, you have to use the -> syntax instead, as if the object were a C struct, to access that variable directly.
An auto-synthesized #property instead creates a protected instance variable (prefixed with an underscore), which is read and set by the synthesized methods. Now, the overhead of using a property is negligible, compared with direct member access, so there's no real reason to stop using properties.
In your example, if you had a MyView* myview, you could set the view b directly, with myview->b = someotherview;. But this would give the class no chance to respond to the update (you would probably write the setter method so you can do something with it), nor does it ensure that the view provided is retained properly. These are the issues that properties were designed to avoid.

Related

instance variables only visible internally in class

NOTE: I am only talking about .m file here.
I am confused by these two things, both are said to be the way to declare internal instance variable:
Way 1:
#interface MyClass ()
// Declare instance variable which is only visible in this class
#end
#implementation MyClass
...
#end
Way 2:
#implementation MyClass {
// Declare instance variable which is only visible in this class
}
...
#end
What are the differences between these two ways of declaring instance variables?
In terms of functionality, there is no difference.
Declaring the ivars in a class extension -- the #interface MyClass() {...ivars...}#end pattern -- does allow you to move the ivar declaration to a header file that could then be used by other classes for direct access for internal-only use, for example.
After the "#interface" line, you can add instance variables within curly braces. That's instance variables, not properties. After the curly braces, or immediately after the "#interface" line if you have no curly braces, you add methods and properties.
So your first comment is wrong. Instance variables can only be added within the curly braces. Properties generate instance variables (usually but not always), but they are not instance variables.
Besides ivar, properties also generate setter and getter method if necessary (according your property attribute). But if you implement the setter and getter synchronously, compiler would not synthesize ivar, since the compiler will assume that you are taking control over the property implementation and won’t synthesize an instance variable automatically.
In Objective C the { } it’s the area where you declare instance variables. You can also use access member declaration in that section like #private #public & #protected. When you declares the "ivars" outside the {} the variable will be a file-scope variable (kind of static) and it won't be an instance variable of your class.
If you use properties (#property) the compiler is smart enough and will create its own ivars with its corresponding setter and getter.
Using a class extension in the implementation file allows you to add ivars or properties (and methods) that are only accessible by the implementation of the class extension. It also allows you to overwrite access of base classes like properties or private methods.

#property/#synthesize equivalent in swift

We used to declare property to pass data between classes as following:
.h file (interface file)
#property (nonatomic) double topSpeed;
.m file (implementation file)
#synthesize topSpeed;
Now there is no interface class, how to pass data between .swift classes ?
Swift provides no differentiation between properties and instance variables (i.e, the underlying store for a property). To define a property, you simply declare a variable in the context of a class.
A swift class is simply a ClassName.swift file.
You declare a class and properties as
class SomeClass {
var topSpeed: Double
var aStrProperty: String
var anIntProperty: Int
//Initializers and other functions
}
You access property values via dot notation. As of Xcode6 beta 4, there also are access modifiers (public, internal and private) in Swift. By default every property is internal. See here for more information.
For more information, refer to the Swift Programming Guide:
Stored Properties and Instance Variables
If you have experience with Objective-C, you may know that it provides
two ways to store values and references as part of a class instance.
In addition to properties, you can use instance variables as a backing
store for the values stored in a property.
Swift unifies these concepts into a single property declaration. A
Swift property does not have a corresponding instance variable, and
the backing store for a property is not accessed directly. This
approach avoids confusion about how the value is accessed in different
contexts and simplifies the property’s declaration into a single,
definitive statement. All information about the property—including its
name, type, and memory management characteristics—is defined in a
single location as part of the type’s definition.
Using Properties.
From the Swift Programming Guide:
Stored Properties and Instance Variables
If you have experience with Objective-C, you may know that it provides
two ways to store values and references as part of a class instance.
In addition to properties, you can use instance variables as a backing
store for the values stored in a property.
Swift unifies these concepts into a single property declaration. A
Swift property does not have a corresponding instance variable, and
the backing store for a property is not accessed directly. This
approach avoids confusion about how the value is accessed in different
contexts and simplifies the property’s declaration into a single,
definitive statement. All information about the property—including its
name, type, and memory management characteristics—is defined in a
single location as part of the type’s definition.
Properties in Objective-C correspond to properties in Swift. There are two ways to implement properties in Objective-C and Swift:
Synthesized/auto-synthesized properties in Objective C -- these are called "stored properties" in Swift. You simply declare it with var topSpeed : Double or let topSpeed : Double = 4.2 in a class declaration, exactly as you would declare a local variable in a function body. You don't get to specify the name of the backing instance variable because, well, there are currently no instance variables in Swift. You must always use the property instead of its backing instance variable.
Manually implemented properties in Objective-C -- these are called "computed properties" in Swift. You declare them in the class declaration like var topSpeed : Double { get { getter code here } set { setter code here } } (for readwrite properties), or var topSpeed : Double { getter code here } (for readonly properties).
It sounds like at least part of your question relates to communicating a given class's interface to other classes. Like Java (and unlike C, C++, and Objective-C), Swift doesn't separate the interface from the implementation. You don't import a header file if you want to use symbols defined somewhere else. Instead, you import a module, like:
import Foundation
import MyClass
To access properties in another class, import that class.
Stored Properties and Instance Variables
If you have experience with Objective-C, you may know that it provides two ways to store values and references as part of a class instance. In addition to properties, you can use instance variables as a backing store for the values stored in a property.
Swift unifies these concepts into a single property declaration. A Swift property does not have a corresponding instance variable, and the backing store for a property is not accessed directly. This approach avoids confusion about how the value is accessed in different contexts and simplifies the property’s declaration into a single, definitive statement. All information about the property—including its name, type, and memory management characteristics—is defined in a single location as part of the type’s definition.
From the Swift Programming Book:
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
I say : typealias is equivalent even more in swift for #synthesize
just look at this link : https://docs.swift.org/swift-book/ReferenceManual/Declarations.html

iOS call properties

I'm a beginner in iOS development and I'm currently watching couple courses online which explain the whole in the backscene getting and setting process.
Somebody thought me that when I'm initializing a variable I should use:
[self setX:1];
And in the rest of the code to acces this variabel I should use:
_x
instead of :
[self x]
The reason for this had something to do with reference counting, but now in the course the person tells me to never use the underscore for anything but in the automatic generated getter and setter?
I know about the dot notation. But concrete question is: "Can I call variabel with the getter and setter without the fear of memory leaks (I'm using ARC) instead of the underscore.
The underlying instance variable for that property is in fact _x. That is how auto synthesised properties work.
However you should consider using the accessors to set the property (using self.x = instead). See this link for more info on Reason to use ivars vs properties in objective c
Your ios version is ios6 that's why it will be direclty get _x.
When you define any property
#Property int x;
ios6 automaticall synthsize using _x; so dont worry you can used _x.

getting value of global variable from .m to another .m

I have tried getting value of global variable from .m to another .m in 2 ways :
Firstly, I tried to import the viewController.m class in another .m class and tried to retrieve the value but I received a linker error.
Secondly, I simply created extern with the string name and then it started working perfectly.
My question is Why import gave me the error and how extern variable recognizes the string name from that particular class ?
( ie : What if I had 2 or 3 variables with the same name in different classes and I type extern and string name which value would I get since I am not importing any class.)
And, Add-on question : When DO you really import the class ?
You really import a class when you need access to it's properties and methods. That might have sounded too obvious, but that's what it really is. Classes are OOP's encapsulation concept personified.
Getting a variable from one point to another can be done in many ways, one could use the userdefaults facility, you could have the variable within the app delegate and then access the value in different classes or you could expose a property on your destination view controller and have the source view controller set that property before transitioning to the destination..to name a few. There are many more methods that are right and wrong depending on the scenario.
Importing a view controller A into another view controller B, simply to have access to a value in A seems like overkill (if not flat out an inappropriate use of the importing mechanism).
This question explains externs further, I have no exposure to them,
Objective-C static, extern, public variables
Hope this helps.
Firstly, I tried to import the viewController.m class in another .m
class and tried to retrieve the value but I received a linker error.
You NEVER import a .m (implementation) file. You only ever import .h (header) files.
My question is Why import gave me the error
In C, there is a rule that any (non-static) global function or variable with a certain name must be defined only once. For a variable, writing its type and name defines it. For a function, the implementation defines it. Thus, having global functions or variables of the same name in two different code files will fail. They will conflict.
Importing a file means take the entire source of the file and insert it there. When you "import" A.m into B.m, the entire source of A.m is inserted into B.m. That means every declaration in A.m now shows up in two code files in your program -- A.m and B.m, hence the error.
You can declare (but not define) a global variable or function more than once. You can declare a variable by using extern without defining it. Declaring it with extern allows you to use a variable even though it is not actually declared in the same code file.
and how extern variable
recognizes the string name from that particular class ? ( ie : What if
I had 2 or 3 variables with the same name in different classes and I
type extern and string name which value would I get since I am not
importing any class.)
As explained above, you can only have one non-static global variable with a given name in your program. It would be an error to have variables with the same name in different files. It is possible for non-static global variables and functions to be accessible from any other part of the program, by its name (and it works through the magic of linking).
Generally, the best practice for a global variable that will be used in many files, is to define it in a .m file (as you're doing), and the declare it extern in the .h file corresponding to that .m file. Then other files that import that header will automatically have access to that variable.
I know this has already been answered in detail, but I just want to offer some clarification.
Declare data that you want to keep private in your .m file. For data that you want to make accessible to other objects, declare in your header .h file. Use properties for all your declarations:
//myViewController.h
#interface myViewController: UIViewController
#property (assign) int myInt;
#property (strong) NSString* someString;
#end
You can access these properties from another object by passing a message to myViewController:
[myViewController setMyInt:20]; //setter
[myViewController someString]; //getter
Or you can use the equivalent dot notation
myViewController.myInt = 20;
myViewController.someString;
(you need to #include "myViewController.h" in any object that wants access to these)
Inside myViewController you access them using 'self':
self.myInt;
self.someString;
This is mediated access via the setter/getter. The backing variable can be accessed directly from inside myViewController (but not from any other object) as _myInt, _someString. This is not advised outside of init and dealloc methods.
A property encapsulates declaration of instance variables and creation of default getters and setters, so you do not need to make a separate variable declaration, and you only need to make your own accessors if you need to change the default behaviour.
Please also refer to my answer here:
Should I declare variables in interface or using property in objective-c arc?

Why must I define variables twice in the Header file?

Why must I define variables twice in the header file? What differences are there between these variables?
The first definition is here:
#interface MyController: UIViewController
{
NSInteger selectedIndex;
}
The second definition is here:
#property (nonatomic) NSInteger selectedIndex;
What you're seeing was required in earlier versions of Objective-C,
but isn't any more.
In the first versions of Objective-C used by NeXT up until the new
runtime was introduced (with Objective-C 2.0 on Mac OS X), all
instance variables had to be declared as part of the class's structure
in its #interface. The reason was that if you subclassed a class,
the compiler needed to know the instance variable layout of the class
so it could see at what offset to put the subclass's instance
variables.
When properties were introduced, synthesized properties had to be
"backed" by an instance variable in the class's structure. Therefore
you had to declare both an instance variable and the property.
All of the above is no longer true. Newer Objective-C is less fragile
in the way it looks up instance variable offsets, which has meant a
few changes:
not all instance variables need to be in the #interface. They can now be defined in the #implementation: though not in categories due
to the possibilities of clashing and other issues.
instance variables for synthesized properties can be inferred and created based on the property definition.
you can programmatically add instance variables to classes you're creating at runtime (only before you've registered the class as
available to the system).
So, to reiterate, you only needed to declare both the instance
variable and a synthesized property in older versions of the
Objective-C language. What you're seeing is redundant and should not
be considered a "best practice".
[Source]
As others have pointed out, it is no longer necessary to declare a backing instance variable for a synthesized property in the header.
To make this a bit clearer though: What you're seeing are not two declarations of the same variable, it is one declaration of the variable and one declaration of the property.
A property is basically a set of methods (in this case selectedIndex and setSelectedIndex:) that are typically used to access instance variables. There is a difference between a property and an instance variable. The property's setter/getter could do more than just set the variable, in your example, it could also e.g. update the UI to reflect the change of the selected index or the getter could infer the index from some other variable (in this case, there might be a selection index path), etc.
Synthesizing a property simply frees you of implementing those methods yourself and provides you with default implementations that simply set the variable, but you could also implement selectedIndex and setSelectedIndex: yourself just like any other method in which case you might either need the instance variable itself or omit it altogether (in case of an inferred property).
In modern runtime you do NOT need to declare them twice. Just use:
In you .h
#property (nonatomic) NSInteger selectedIndex;
The part between the {} is the declaration of the iVar. And with your #property you declare getter and setters. In modern runtime if you just use the code above you say basicly the same (your iVar is now _selectedIndex).

Resources