Declare instance variable in Objective-C and set in Swift - objective-c

I want to be able to set the value of an instance variable from my Objective-C class in my Swift class. In my Swift class, I want to be able to say something like cameraViewController.ingestViewController = self and have that set the value of ingestViewController in my Objective-C class. Here is some code to demonstrate:
PhotoViewController.swift:
class PhotoViewController : UIViewController {
let cameraViewController = // reference to the CameraViewController
cameraViewController.ingestViewController = self
}
CameraViewController.h:
#interface CameraViewController : GSKCameraViewController
#end
CameraViewController.m:
#interface CameraViewController ()
#property (nonatomic, strong) UIView *toolbar;
#property (nonatomic, strong) UIButton *cameraButton;
#property (class, nonatomic, strong) UIViewController *ingestViewController;
#end
#implementation CameraViewController
UIViewController *ingestViewController
// rest of implementation
#end
I continue to get the error Value of type 'CameraViewController?' has no member 'ingestViewController'.

#property (class, nonatomic, strong) UIViewController *ingestViewController;
This is a class property, not instance variable property.
So just remove class attribute.

You've declared the ingestViewController property as a class property, not an instance property.
Remove the class attribute of the #property.
#property (nonatomic, strong) UIViewController *ingestViewController;
Once that is fixes, you need to make the property public. Move it to the .h file:
#interface CameraViewController : GSKCameraViewController
#property (nonatomic, strong) UIViewController *ingestViewController;
#end
All of the properties in the .m are private.
Lastly, remove the unnecessary line:
UIViewController *ingestViewController
from the .m file. That is actually declaring a global variable and is not in any way associated with the property of the same name.

Related

Difference between declaring properties in interface

Can someone tell me what is the difference between declaring a property in interface like this
#interface RootViewController : UITableViewController {
NSDate *timestamp;
}
#end
and
#interface RootViewController : UITableViewController
#property (nonatomic, retain) NSDate *timestamp;
#end
and
#interface RootViewController : UITableViewController {
NSDate *timestamp;
}
#property (nonatomic, retain) NSDate *timestamp;
The former is not a property at all. It's an instance variable declaration.
The latter is a property, which is a term for a getter/setter pair and their backing instance variable.
The instance variable that's synthesized for you will be prefixed with _. So if you look at RootViewController using the Objective C runtime APIs, you can see it actually has an ivar named _timestamp.

Why declare the variables of public properties on the interface with the property declarations?

I'm looking at this code below and trying to figure out which of the two of us... (me, or the person who wrote it) doesn't know what they're doing.
Why did he/she declare properties, then declare matching variables as well?
I can't ask the person because this project is inherited from a group long gone.
#interface LayerList : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
UITableView *tvList;
ArcGisViewController *mapController;
NSArray *fileList;
}
#property (nonatomic, strong) IBOutlet UITableView *tvList;
#property (nonatomic, strong) ArcGisViewController *mapController;
#property (nonatomic, strong) NSArray *fileList;
-(void)visibleSwitchValueChanged:(id)sender;
-(IBAction) Cancel;
#end
This was the usual way in a day when you had to synthesize the properties manually before auto-synthesizing was introduced.

How to access a read-only propertly (re-defined readwrite in class continuation) from a derived class

I am in the following scenario:
I have define a class with a property to access the activeController that i made read-only
#interface BaseViewController : UIViewController
#property (nonatomic, weak, readonly) UIViewController *activeController;
#end
In the class continuation i have define the property as readwrite as i want to be able to set the active controller only within the class:
#interface BaseViewController ()
#property (nonatomic, weak, readwrite) UIViewController *activeController;
#end
How do i make the readwrite property accessible from a derived class?
#interface ChildViewController : BaseViewController
#end
The compiler only see the property defined as read-only in the derived class and i want to be able to make use of property within my derived class and set the activeview controller in the derived class.
It's better not to expose publicly an instance variable unless you really need to.
The standard pattern for making some additional parts of the class accessible to subclasses is making a separate header file, e.g. BaseViewController+Private with the declaration of readwrite. This file can then be included by 'insiders', that is class and it's subclasses.
You need to change the header file for BaseViewController to
#interface BaseViewController : UIViewController
{
__weak UIViewController *_activeController;
}
#property (nonatomic, weak, readonly) UIViewController *activeController;
which will allow you to us the following class continuation in the both the base and the child
#interface ChildViewController ()
#property (nonatomic, weak, readwrite) UIViewController *activeController;
#end

NSObject subclass as a property

I want to use my class as a property in my project. The idea is that i have a class which contains all list ellements. The basic idea i show below in graph:
So i have a myContainerClass object, and i want to do in some other class:
#property (strong,nonatomic) MyContainerClass *obj;
and here i have error! I figure out that i can only use Foundations type as a #property. But Why? What is replacement for doing that (passing an object)?
No, you can use any class you like as a property
#property (nonatomic, strong) MyContainerClass* obj;
is perfectly legal provided that the compiler knows that MyContainerClass is a class. To do that in the header file, the best way is to use an #class forward declaration:
#class MyContainerClass;
#interface SomeOtherClass : NSObject
// method an property declarations
#property (nonatomic, strong) MyContainerClass* obj;
#end
And then include the header file in the implementation:
#import "MyContainerClass.h"
#implementation SomeOtherClass
#synthesize obj;
// other stuff
#end
What is the error you are getting? May be you are not importing MyContainerClass to where you want to use it.
#import "MyContainerClass.h"
Declare a category for an object that you want to add your property to:
#interface NSObject (MyContainerClassAdditions)
#property (nonatomic, strong) MyContainerClass *myContainerClass
#end
Then implement the setter and getter methods using objective c associated object trick:
#import <objc/runtime.h>
#implementation NSObject (MyContainerClassAdditions)
- (void)setMyContainerClass:(MyContainerClass *)myContainerClass {
objc_setAssociatedObject(self, "myContainerClass", myContainerClass, OBJC_ASSOCIATION_ASSIGN);
}
- (MyContainerClass *)myContainerClass {
return objc_getAssociatedObject(self, "myContainerClass");
}
#end

getters and setters for custom classes

If you synthesize a custom class, do getters and setters get created for it?
This is the custom class I created.
// MyClass.h
#import <Foundation/Foundation.h>
#interface MyClass : NSObject <NSCoding> {
NSString *string1;
NSString *string2;
}
#property (nonatomic, retain) NSString *string1;
#property (nonatomic, retain) NSString *string2;
#end
Here I declare an object of that class as a property
// DetailViewController.h
#import <UIKit/UIKit.h>
#import "MyClass.h"
#interface DetailViewController : UIViewController {
MyClass *myObject;
}
#property(nonatomic, retain) MyClass *myObject;
#end
Here I synthesize the object.
#import "DetailViewController.h"
#import "MyClass.h"
#implementation DetailViewController
#synthesize myObject;
So does it have getters and setters?
When I try to run this code inside RootViewController.m
DetailViewController.myObject = [theArray objectAtIndex:indexPath.row];
I get an error saying "Accessing unkown 'setMyObject:' class method. Object cannot be set - either readonly property or no setter found.'
Only if you declare the desired instance variables as properties, then synthesize propname;, will getters and setters be created. Now, what kind of code goes into the getters and setters depends on what property attributes you define (nonatomic/atomic, assign, retain, copy)
EDIT to OP's revised question: Yes a getter/setter will be created for the myObject instance variable of the DetailViewController class
DetailViewController.myObject = [theArray objectAtIndex:indexPath.row];
You are attempting to set a class variable that isn't defined. DetailViewController is of type Class, not DetailViewController. Perform the same operation on an instance of DetailViewController and you should be all set.