NS_ENUM error when declared before class instance variables - ios

Example .h file:
#interface MyClass : NSObject
typedef NS_ENUM(int, myType) {
Something,
SomethingElse,
SomethingElseElse,
YetAnotherSomethingElse
};
{ //Error On This Line: Expected Identifier or '('
int aInstanceVariable;
}
//Some Methods go here
#end
Why am I getting that error (see the comment in the code above)? It works fine when below the class instance variable declaration, but I would like to use it as the type for one of my instance variables.

Thanks to #CarlVeazey, I discovered that the answer was simple: Move the typedef declaration to above #interface. The reason for this is that types cannot be owned by a class or an instance of a class, and therefore cannot be in the interface for a class.

Related

Objective C - Called object type 'BOOL' (aka 'bool') is not a function or function pointer

Working on a legacy hybrid iOS project. Created one new Swift util class in ConsentManager.swift, like below,
import Foundation
public class ConsentManager: NSObject {
#objc static let sharedInstance = ConsentManager()
#objc private override init() {}
#objc public func isDataPermissionConsentRequired() -> Bool
{
…
return value; // based on logic
}
}
Called the method from another objc class, ConsentChecker.m like,
#interface ConsentChecker ()
{
}
#end
#implementation ConsentChecker
-(void)checkConsent {
// GETTING ERROR IN THE FOLLOWING LINE
if (ConsentManager.sharedInstance.isDataPermissionConsentRequired()) {
…
}
}
#end
Getting compiler error:
Called object type 'BOOL' (aka 'bool') is not a function or function pointer
Why and how to resolve it?
The reason you're hitting this is that methods in Objective-C which take no arguments may be called implicitly using dot syntax similar to Swift's, but not exactly like it. A method declared like
// Inside of SomeClass
- (BOOL)someMethod { /* return something */ }
can be called either as
SomeClass *instance = ...
// Traditional Obj-C syntax:
BOOL value = [instance someMethod];
or
// Dot syntax accessor:
BOOL value = instance.someMethod;
Note that the dot syntax version does not use parentheses to denote the call. When you add parentheses like you would in Swift, Obj-C determines that you are trying to call the returned value from the method as if it were a function:
instance.someMethod();
// equivalent to:
BOOL value = [instance someMethod];
value(); // <- Called object type 'BOOL' (aka 'bool') is not a function or function pointer
You cannot call a BOOL like you can a function, hence the error.
#Dávid offers the more traditional Obj-C syntax for calling this method, but alternatively, you can simply drop the parentheses from your call:
if (ConsentManager.sharedInstance.isDataPermissionConsentRequired) {
Objective-C-ism note:
Dot syntax is most idiomatically used for method calls which appear like properties (e.g. boolean accessors like your isDataPermissionConsentRequired), even if the method might need to do a little bit of work to return that value (think: computed properties in Swift).
For methods which perform an action, or which return a value but might require a significant amount of work, traditional method call syntax is typically preferred:
// Prefer:
[instance doTheThing];
NSInteger result = [instance performSomeExpensiveCalculation];
// over:
instance.doTheThing;
NSInteger result = instance.performSomeExpensiveCalculation;
The Obj-C syntax for executing methods is different from Swift's dot syntax.
This is the correct syntax:
if ([ConsentManager.sharedInstance isDataPermissionConsentRequired]) {
If u want to call swift function on obj-c class you use to obj-c syntax
Correct Syntax is:
if ([ConsentManager.sharedInstance isDataPermissionConsentRequired]) {
// Write logic here
}

iOS: Objective-C creating class property error: Use of undeclared identifier

I'm trying to use class property following this example. But I'm getting the following error:"Use of undecleared identifier '_myProperty'".
Here is my implementation:
#interface myClass()
#property (class,strong,nonatomic) NSString *myProperty;
#end
+ (NSString*)myProperty
{
if (!_myProperty) {
}
return [NSString new];
}
Why I'm getting this error? or any of you knows a work around this?
I'll really appreciate your help
Class properties don't get synthesized in Objective-C. You have to provide your own backing variable and your own getter/setter:
static NSString *_myProperty = nil;
+ (NSString *)myProperty {
if (!_myProperty) {
_myProperty = [NSString new];
}
return _myProperty;
}
+ (void)setMyProperty:(NSString *)myProperty {
_myProperty = myProperty;
}
Class properties and never auto-synthesised, the getter and/or setter must be implemented, and no backing variable is automatically created for them.
If your property needs a variable you must declare one, use a static global in the implementation file - that is effectively a "class variable" in Objective-C. Alternatively if you only require a getter you can declare a static variable local to the getter itself, further reducing its visibility and keeping the getter and variable together as a package.
HTH
In fact, class property is not a member of a class. So it will be created at once and all instances will use this one. So there is nothing to synthesize.

Swift instance variable with protocol

I have to translate the following lines of Objective-c code into swift. This is a sample from the Objective-c JSONModel-Framework where the Optional protocol provided by the Framework is applied to an instance variable of type NSString. I found a related post but i didn't managed to achieve it. With my MYModel.swift implementation Xcode complains Cannot specialize non-generic type NSString
thx for your help!
MYModel.swift
#objc(MYModel) public class MYModel : JSONModel {
...
public var name : NSString<Optional>
...
}
MYModel.h
#interface MYModel : JSONModel
...
#property (strong, nonatomic) NSString<Optional>* name;
...
JSONModel.h
...
/**
* Protocol for defining optional properties in a JSON Model class. Use like below to define
* model properties that are not required to have values in the JSON input:
*
* #property (strong, nonatomic) NSString<Optional>* propertyName;
*
*/
#protocol Optional
#end
...
The < and > are not for conforms to protocol. It is for Types with generics like Array:
Array<T>
so you can write var a: Array<String>.
You want something else, a variable should be a Type String and conform to the protocol
You can extend String with the protocol and add the needed functions yourself.
Since your Optional protocol is empty, it is enough to write:
extension NSString: Optional {} // you can use String if you like
To create the protocol write in Swift:
protocol Optional {}
You can Objective-C create the protocol, too.
You should not use Optional, because there is already one, but because Swift has namespacing, it works.
You could of course write something like that:
extension NSString: JsonOptProtocol {}
protocol JsonOptProtocol {} // or create that in Objective-C like you did
Documentation link.
Optional is a type declared in the standard library of Swift, at the moment JSONModel is not compatible with Swift because of this.

Objective-C function argument and static variable same name

I am having some issue about naming overridings of static variables in objective-c.
My .h file is:
#import <Foundation/Foundation.h>
#interface FetchClass : NSObject
+ (void)initWithNSManagedObjectContext:(NSManagedObjectContext *) managedObjectContext;
#end
And my .m file is:
static NSManagedObjectContext * managedObjectContext;
#implementation FetchClass
+ (void)initWithNSManagedObjectContext: (NSManagedObjectContext *) managedObjectContext{
FetchClass.managedObjectContext = managedObjectContext;
}
However, I get the error
"Property managedObjectContext not found on object of type FetchTasks"
So, the problem is, function argument managedObjectContext is of course overriding the static variable of the same name. That is why I have to get the static variable through Class.staticVariableName. But this time I get error as I mentioned above.
However If I change the static variable name to some other name , like:
static NSManagedObjectContext * managedObjectContextOtherName;
#implementation FetchClass
+ (void)initWithNSManagedObjectContext: (NSManagedObjectContext *) managedObjectContext{
managedObjectContextOtherName = managedObjectContext;
}
It works perfectly. My question is that, how to use these variables (static variable and function argument variable) if they have same name?
A static variable, like your managedObjectContext, is the closest thing to a class variable that Objective-C provides but it is not the same thing and this is why you get errors doing what you are trying - you cannot resolve your reference by qualifying it with the class name.
In (Objective-)C a static variable declared outside of any function/method has global lifetime and file scope - i.e. the variable always exists but is only visible from within the same source file as its declaration. There is no "file scope" qualifier you can use to resolve ambiguity/hiding when reference a static, any variable with the same name in an inner scope will hide the static.
In your case you can just use:
+ (void)initWithNSManagedObjectContext:(NSManagedObjectContext *)_managedObjectContext
{
managedObjectContext = _managedObjectContext;
}
(And there is no need to change your declaration of initWithNSManagedObjectContext: in the interface - parameter names are not required to match - so your "public" declaration doesn't require _'s in the names if you don't wish it to.)
Method arguments and instance variable should have different names. When they are the same, the compiler should warn you that it using the method variable.

Getting error use of undeclared identifier "value" when assigning parameter to variable

When I assign value to age, I get this error:
#interface Person : NSObject
{
int age;
}
-(void)setAge;
#end
I tried to use self.age, yet it did not work
Here is my .m file:
#implementation Person
-(void)setAge(int)value
{
age = value;
}
#end
I tried several differnet things. ..I get this error when I type this: age = value; do you know why this is?
You should add:
-(void)setAge:(int)value;
In the header file because the current method specification you have there doesn't have a parameter.
Your method in the implementation should also have the same spec as it's missing a colon currently.
You have actually declared one method (-setAge) and implemented another (-setAge:, note the colon). You should really declare age as a property and avoid explicit ivars as much as possible. Also, I hope you have properly formatted the class in your real code.
#interface Person : NSObject
#property (nonatomic) int age;
#end
#implementation Person
-(void)setAge:(int)value
{
_age = value;
}
#end
Note that it is no longer necessary to explicitly #synthesize properties, and they automatically synthesize with an underscored ivar.

Resources