I'm new to Objective-C and I'm having trouble with the whole nonatomic, strong, weak, etc. I'm wondering if I will have any issues using Core Data with float values which are defined like so:
#property (nonatomic) float * rating;
#property (nonatomic) float * mRating;
Should I declare the differently?
Yes, you should declare them without asterisks:
#property (nonatomic) float rating;
#property (nonatomic) float mRating;
Asterisks indicate pointers. All Objective C classes are declared with asterisks, because instances are referred to through pointers. Primitives such as floats, ints, etc. are defined as values, i.e. without asterisks. Same goes for typedef-ed types such as CGFloat and NSInteger: scalar fields of these types should be defined without an asterisk.
You should definitely lose the *, unless you are meaning to create a pointer. Outside of that it looks great!
Related
hi iam learning IOS development & for learning porpoises
i want to know how to make this property nullable in objc
(this Four #property)
#property (nonatomic) BOOL Hood;
#property (nonatomic) BOOL smartclean;
#property (nonatomic) t_ShirtSize size;
#property (nonatomic) NSUInteger newsoftness;
because
when i use nullable i get this Error
#property (nullable,nonatomic) BOOL Hood;
Nullability specifier 'nullable' cannot be applied to non-pointer type 'BOOL' (aka 'signed char')
what is the Right way to make all 4 property nullable how can i do that (accept Null)
this is M file for The My app
-(instancetype _Nonnull) initWithSize:(t_ShirtSize)size
Hood: (BOOL)hoody {
self = [super init];
if(self) {
Hood = hoody;
_size = size;
}
return self;
}
If you absolutely need a nullable BOOL, you can use NSNumber as a wrapper:
#property (nullable,nonatomic) NSNumber* Hood;
use Hood = #YES; /* or #NO */ to assign a value, and Hood.boolValue to read the value again.
Note that, as others have said already, this is not a full replacement for Swift's optionals, and you have to take extra care to always use the correct data type - the compiler won't help you if you accidentally store a floating point value in your "nullable NSUInteger".
A BOOL is a primitive, not an object. If you need an object, the usual thing is to wrap your BOOL in an NSNumber:
https://developer.apple.com/documentation/foundation/nsnumber/1415728-initwithbool?language=objc
https://developer.apple.com/documentation/foundation/nsnumber/1410865-boolvalue?language=objc
Now you have an NSNumber, so you have something that can be nil to indicate there is no object there.
The nullable annotation helps Swift understand whether a reference is optional or not when Objective-C code interfaces with Swift. It doesn't change the operation of Objective-C in any way.
nil can be assigned to a pointer in Objective-C even if it doesn't have a nullability annotation; that is just the nature of C pointers.
Scalar value types (Integers, bools etc) cannot be null in Objective-C, they always have a value since there is no pointer to their value. Their value is stored directly.
There is no direct Objective-C support for optional or nullable value types as there is in Swift
In Swift, an optional is actually a struct containing the wrapped value and a property that indicates whether the optional has a value or not. The compiler hides this detail from you.
You could use NSNumber. This wraps scalar value types in an object. The object reference can be nil and so is nullable
#property (nonatomic, nullable) NSNumber* Hood;
#property (nonatomic, nullable) NSNumber* smartclean;
#property (nonatomic) t_ShirtSize size;
#property (nonatomic, nullable) NSNumber* newsoftness;
You don't need that nullability specifier anymore with BOOL properties, and perhaps also for the NSUInteger.
For BOOL, the reason why you don't need it is that it's by default 0 or <nil>.
What is the difference between these two declarations in Objective-C?
I have been looking at some Apple source code example and they used the second one in various circumstances. I just wanted to understand why and when is best to use the second version rather than the first one (I know the difference between strong, weak, atomic, nonatomic).
#property(nonatomic, strong) NSObject * myObject;
// vs
#property NSObject * myObject2; //No additional qualifiers
#property NSObject * myObject2
// is same as
#property (atomic,strong) NSObject * myObject2
which one to use, is developer's personal choice
I have the following enum:
typedef NS_ENUM(NSUInteger, GraphType) {
GraphTypeRawData,
GraphTypeFilteredData
};
The compiler accepts without warning me declaring it as a property primitive, or as a pointer:
#property (nonatomic, assign) GraphType graphType;
VS
#property (nonatomic, assign) GraphType *graphType;
Which is the correct one to use? (And why?)
It's a primitive type. Don't use a pointer unless you have a very clear and specific reason to track a pointer to a primitive type (which will be very rare).
I have a hard time getting myself introduced to Objective-C and iOS programming. I tried to search for this problem, but the results weren't explained simple enough.
So I have a viewController.h and a viewController.m. In the .h I add my Labels/Buttons etc. between #interface and #end
#property ( nonatomic, strong ) UILabel *facebookLoginTextLabel;
#property ( nonatomic, strong ) UIButton *facebookLoginButton;
And in the .m I'm simply synthesizing them between #implementation and the first method
#synthesize facebookLoginTextLabel = _facebookLoginTextLabel;
#synthesize facebookLoginButton = _facebookLoginButton;
The problem I'm facing now, is what to do with other values? As an example. I have a boolean value. Where do I declare it? How do I set it? How do I get the value? It's way too confusing for me. The same counts for an NSInteger?
I want, dependent on the ifcase, set the NSInteger to 0, 1 or 2. How do I achieve this? I tried getting and setting like this
.h
#property ( nonatomic ) CGFloat *width;
.m
#synthesize width = _width;
viewDidLoadMethod
_width = [self returnScreenWidth];
returnScreenWith method
- ( CGFloat ) returnScreenWidth {
return [UIScreen mainScreen].bounds.size.width;
}
This doesn't work. Why? How do I set, how do I get? How do I declare variables? Way too confusing from a PHP and an Android-Developer.
First of all, it is CGFloat width not CGFloat *width as it is a C struct, not an Objective C class where you define the property in the header file:
#property (nonatomic) CGFloat width;
Instead of accessing the under-score instance variable, just use self.width whereby you access the #property using self.
Remember, all basic/primitive data types like (int, float, char, BOOL) need not be used as you are doing, always use assign.
Yes BOOL is a primitive, as this is typedef to char.
It should be defined as :
#property (assign) <primitivetype> propertyName;
Also to note down, with new compiler (I hope you are using Xcode4.2 onwards i.e LLVM),
#synthesize propertyName is done automatically by the compiler as
#synthesize propertyName = _propertyName;
atomic and nonatomic depends on your requirement, so is the pointer to int or float.
Coming from Java, I'm pretty used to autoboxing, where an int is automatically wrapped to an Integer when needed, and an Integer may be unboxed into a primitive. Is there something similar that I can rely upon in iOS5?
currently, I'm using core data, and it takes a lot of typing to keep having to type
number.intValue
//or
number.boolValue
is there some way to use an NSNumber directly in equations and such? for example:
int x = 5+ nsNumberInstance;
Furthermore, every time I need to re-assign a number in the core data, I'm creating a new object like this.
managedObject.dynamicProperty = [NSNumber numberWithInt: int];
is there a better way to change the value of an already created NSNumber? What kinds of nifty shortcuts may I use to save myself from carpal tunnel 10 years from now?
Thank you!
Actually, when you are in your data model, and you use the "Create NSManagedObject subclass" menu item, there is an option that you can select titled "Use scalar properties for primitive data types".
This automatically handles this for you in many cases.
Here are some examples:
BOOL:
#property (nonatomic, retain) NSNumber * aBool;
becomes
#property (nonatomic) BOOL aBool;
NSDate:
#property (nonatomic, retain) NSDate * aDate;
becomes
#property (nonatomic) NSTimeInterval aDate;
Integer 32:
#property (nonatomic, retain) NSNumber * aNumber;
becomes
#property (nonatomic) int32_t aNumber;
and
Float:
#property (nonatomic, retain) NSNumber * aFloat;
becomes
#property (nonatomic) float aFloat;
NSDecimalNumber and NSString stay the same.
You can change these yourself in the previously generated header file if you have already generated the subclasses and the accessor methods will automatically update without having to re-generate the subclass.
Outside of Cocoa bindings, I can't think of many other places that have autoboxing of scalar types in Cocoa or Cocoa touch, so unfortunately you're out of luck there.
You don't really gain anything by working with NSNumbers in calculations, so dealing with the objects there isn't really necessary. It's much easier to work with scalar types, and then convert back and forth between NSNumbers when storing these numbers in Core Data, arrays, etc. The one case where you'd want to stay in this form would be NSDecimalNumbers, which do not represent numbers as your standard floating point values, and thus avoid the glitches you see when trying to work with decimals in those types.
Core Data stores objects, so you're not going to get around that at a base level, but you can make your life a little easier by using custom accessors on your NSManagedObject subclasses that take and return scalar values. Apple has an example of this in the "Managed Object Accessor Methods" section of the Core Data Programming Guide, where they show how to set up an accessor for a CGFloat value, instead of using an NSNumber:
#interface Circle : NSManagedObject
{
CGFloat radius;
}
#property CGFloat radius;
#end
#implementation Circle
- (CGFloat)radius
{
[self willAccessValueForKey:#"radius"];
float f = radius;
[self didAccessValueForKey:#"radius"];
return f;
}
- (void)setRadius:(CGFloat)newRadius
{
[self willChangeValueForKey:#"radius"];
radius = newRadius;
[self didChangeValueForKey:#"radius"];
}
#end
As a side note, using the dot syntax for -intValue and -boolValue, while it works, is not recommended. These are not properties, but one-way methods that extract values from the NSNumbers. Use brackets when dealing with them to make this clear in your code.