Setting property of objective-C class from Swift - ios

I have a class MyClass subclassed from NSObject. It is written in Objective-C. It has a property with custom getter and setter:
#interface MyClass : NSObject
#property (getter = getIsBypassEnabled, setter = setIsBypassEnabled:) BOOL isBypassEnabled;
#end
And both of these functions are defined in implementation:
#implementation MyClass
// Initializer and other stuff
// ...
- (void) setIsBypassEnabled: (BOOL) newValue
{
_value = newValue;
}
- (BOOL) getIsBypassEnabled
{
return _value;
}
#end
But when I try to set the property from Swift like:
let objcClass = MyClass()
objcClass.isBypassEnabled = true
I get an error 'isBypassEnabled' has been renamed to 'getIsBypassEnabled'. But I need to set the value, not get it!
Trying
objcClass.setIsBypassEnabled(true)
gives me an error that my class has no such member.
Declaring
- (BOOL) getIsBypassEnabled;
- (void) setIsBypassEnabled: (BOOL) newValue;
explicitly in .h file does not help either.
How do I resolve the issue? Thank you.

#interface MyClass : NSObject
#property (getter = getIsBypassEnabled, setter = setIsBypassEnabled:) BOOL isBypassEnabled;
#end
is mapped to Swift as
open class MyClass : NSObject {
open var getIsBypassEnabled: Bool
}
so you can set the property actually with
let objcClass = MyClass()
objcClass.getIsBypassEnabled = true
I don't know if this mapping is intended or not, you might want to
file a bug report.
You can also override the Swift mapping with
#interface MyClass : NSObject
#property (getter = getIsBypassEnabled, setter = setIsBypassEnabled:) BOOL isBypassEnabled
NS_SWIFT_NAME(isBypassEnabled);
#end
and then
let objcClass = MyClass()
objcClass.isBypassEnabled = true
works as intended.

Related

Why NSObject's instance method could be called as a class method

I add a category for NSObject
#interface NSObject (Test)
- (nonnull NSString *)nameOfClass;
#end
#implementation NSObject (Test)
-(NSString *)nameOfClass {
return [self new_nameOfClass];
}
#end
when using, I can use it as a class function.
Objc
[UITableViewCell nameOfClass];
swift
UITableViewCell.nameOfClass()
but If I create a sub class of NSObject, and add a function using category
#interface TestObject : NSObject
#end
#interface TestObject (Test)
- (nonnull NSString *)testFunction;
#end
#implementation NSObject (Test)
-(NSString *) testFunction {
return #"testFunction";
}
#end
I can not use it as
[TestObject testFunction];
if I create a extension for NSObject
#objc
public extension NSObject {
#objc(new_nameOfClass)
func new_nameOfClass() -> String {
return String(describing: type(of: self))
}
}
I can use it as a class function in Objc file, but. I can not use it in swift.
[TestObject new_nameOfClass];
TestObject.new_nameOfClass()
error: Instance member 'new_nameOfClass' cannot be used on type 'TestObject'; did you mean to use a value of this type instead?
Questions
why NSObject's category's instance function can be used as class function?
why it not work in NSObject's subclass?
why swift's extension for NSObject don't have. same behavior?
please refer these docs.
http://www.cocoawithlove.com/2010/01/what-is-meta-class-in-objective-c.html
http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html
make that function as class function
objective c
#interface TestObject : NSObject
#end
#interface TestObject (Test)
+ (nonnull NSString *)testFunction;
#end
#implementation NSObject (Test)
+(NSString *) testFunction {
return #"testFunction";
}
#end

Set an Integer value from one class to another

I have been trying to set an Integer value from one class to another like below, but i can't do this.
#interface ClassA : UIViewController {
}
#property(nonatomic, assign) int m_selrow;
+ (void)setRowSelected : (int)selecetedRow;
#end
#implementation ClassA
+ (void)setRowSelected : (int)selecetedRow {
m_selrow = selecetedRow;
}
#end
//Accessing from different Class,
//Class B implementation:
[ClassA setRowSelected:indexPath.row];
Problem is, it says "m_selrow is use of undeclared identifier from setRowSelected() method. How to properly use the variable and set it from another class.
Interface should inherit from something, I changed it to NSObject
I also added static declartion to of member field to class A
After fixing those, it works smoothly.
Here are my changes:
#interface ClassA : NSObject{
}
#property(nonatomic, assign) int m_selrow;
+ (void)setRowSelected : (int)selecetedRow;
#end
#implementation ClassA
static int m_selrow;
+ (void)setRowSelected : (int)selecetedRow {
m_selrow = selecetedRow;
NSLog(#"============= > %d", m_selrow);
}
#end
[ClassA setRowSelected: 1];

How to compare instances declared as id<protocol> in Objective-C

I have a class that has a property declared as type id that adheres to a protocol and I'd like to ensure equality for it.
How do check for value equality on an property declared as type id?
#interface MyClass : NSObject
#property (nonatomic, copy) NSString *name;
#property (nonatomic, strong) id<SomeProtocol> attribute;
#end
#implementation MyClass
- (BOOL)isEqual:(id)object {
if (self == object) {
return YES;
}
if (![object isKindOfClass:[MyClass class]]) {
return NO;
}
return [self isEqualToMyClass:(MyClass *) object];
}
- (BOOL)isEqualToMyClass:(MyClass *)rhsValue {
if (rhsValue == nil) {
return NO;
}
return
([self.name isEqualToString:rhsValue.name] &&
// Compiler produces error: Error:(90, 36) no known instance method for selector 'isEqual:'
[self.attribute isEqual:rhs.attribute]);
}
#end
SomeProtocol is defined as:
#protocol SomeProtocol <NSObject>
#end
Class that extends SomeProtocol:
#interface MyAttributeClass : NSObject <SomeProtocol>
#end
MyAttributeClass implements the protocol SomeProtocol and it has its own isEqual and when an instance of it is stored by MyClass in attribute, I'd like to be able to check that the values are equivalent.
It is MyAttributeClass that gets assigned into MyClass:
MyClass *myClass = [[MyClass alloc] init];
myClass.name = "HAL";
myClass.attribute = [[MyAttributeClass alloc] init];
Probably you forgot to import the header containing the protocol definition. (Instead of only having a forward declaration.) Add that in front of the implementation.

Define setter method on property set

Is there a way to define a setter method that will run on setting a property like:
i want to call
object.something = 0;
meanwhile in object class i want to achieve something like
- (void)setSomething:(NSInteger)something{
self.something = something;
// some other work too
}
What you want is called property.
you define property in class #interface like:
#interface MyClass()
#property (strong, nonatomic) SomeClass *object;
#end
It will automatically create ivar _object, setter and getter for it.
You can override accessor methods. But if you override both setter and getter, you need to synthesize property like:
#implementation MyClass
#synthesize object = _object;
//setter
- (void)setObject:(SomeClass *)object
{
_object = object;
}
//getter
- (SomeClass *)object
{
return _object;
}
//class implementation
#end
You can do it like this:
#property (nonatomic, weak, setter = setSomething:) UIImageView *photoImageView;
Anyway, setSomething: is the default method for a property named something. You just need to replace self.something with _something, as pointed in the comments.

objective c - Access private var from public function

Newbie to objective C...
NOTE: This is a conceptual problem, as I'm trying to translate "public and private" from what I know about other languages.
How can I access the "stringB" ivar through the "public" method?
myClass.h
#interface myClass : UIViewController {
}
#property (nonatomic, retain) NSString *stringA;
#property (nonatomic, retain) NSString *stringB;
- (void)dealWithStringA;
+ (void)dealWithStringB;
myClass.m
#import "myClass.h"
#interface myClass () {
}
#end
#implementation myClass
// My "private" function
- (void)dealWithStringA
{
return _stringA;
}
// My "public" function
+ (void)dealWithStringB
{
// Errors with: Instance variable "stringB" accessed in class method
return _stringB;
}
The method starting with a + is called a class method in objective C where a method starting with - is an instance method. An instance method can be performed on an instance of that class only.
Also the return type for your method would be an NSString since you are expecting to get a string object from that method.
For a class method, you'll need to create an autoreleasing instance of that class and then perform operations on that instance.
For eg.
+ (NSString*)dealWithStringB
{
MyClass *myClass = [[[MyClass alloc] init] autorelease];
myClass.stringB = #"Its String B";//It's an absurd example
return myClass.stringB;
}
You are wrong with understanding "+", "-" - it's not about private / public.
To have a private function you should implement that in your .m file:
#interface YourClass ()
- (id) privateMethod;
#end
Everything you declare in .h file will be public:
#interface YourClass : NSObject
- (id)someMethod //public
#end
"+" is used for static functions so you can call them without having an instance of a class.
For example in your case:
[myClass dealWithStringB];
and for "-" function you need instance.
[[[myClass alloc] init] dealWithStringA];
The static functions can be used when you don't need any properties from a class or to they are pretty often used to create instances of classes.
The "+" prefix means class method, not public. A "-" stands for instance method, not private.
Both public and private methods can access the private state of the class or instance.
myClass.h (Similar to yours)
#interface myClass : UIViewController
{
}
#property (nonatomic, retain) NSString *stringA;
#property (nonatomic, retain) NSString *stringB;
- (void)dealWithStringA;
+ (void)dealWithStringB;
#end
myClass.m
#implementation myClass
#synthesize stringA ;
#synthesize stringB ;
static myClass* instance = nil;
+(void) dealWithStringB
{
if(instance==nil)
{
instance=[myClass alloc]init];
}
else
{
//Access the field this way
printf("#"The string content is %#",instance.stringB);
}
}
Hope its Clear!!!

Resources