Can't access from Objective-c to swift's member properties - objective-c

I have swift class like this.
class Note: NSObject{
var soundUrl: URL!
var sPosi: Int!
var contNum: Int!
}
then from Objective-c I would like to access these members.
However There is difference betwwen URL type and Int type.
I think I include correctly in both (.h) (.m) file
in Quesion.h
#class Note
#interface Question : NSObject{
Note * QNotes[70];
}
in Question.m
#import "QuesionNote-Swift.h"
- (id)init
{
// QNote array correctly declared and have each Note class instance.
int i = QNotes[i].sPosi; // Question.m:135:26: Property 'sPosi' not found on object of type 'Note *'
int j = QNotes[Q].contNum; //Question.m:145:37: Property 'contNum' not found on object of type 'Note *'
NSURL * k = QNotes[QPosiNum].soundUrl // it doesn't show compile error!!

Related

Using an Objective C enum in Swift back in Objective C

I have an enum defined in Objective C and used as a datatype in a Swift object.
Now I'm using that swift object in Objective C and I'd like to access the property.
However the property isn't added to the "xxxx-Swift.h" file in the class. I know it's possible to use Swift enums in Obj C with #objc prepending it but I don't have much control over this enum since it's auto generated from existing Objective C code.
I'm not sure exactly what your use case is, but here is a quick example of how an enum defined in Objective-C can be used in a Swift class, which can in turn be used in Objective-C.
Here is the Objective-C header (oclib.h):
#ifndef oclib_h
#define oclib_h
#import <Foundation/Foundation.h>
typedef enum {A, B, C} oc_enum_t;
void useSwiftClassInC();
#endif /* oclib_h */
Here is the corresponding Objective-C .m file (oclib.m):
#import "oclib.h"
#import "swift_c_1-Swift.h" // Need this to have access to Swift types; the swift_c_1 part will be your product module name.
void useSwiftClassInC() {
UseEnum *ue = [[UseEnum alloc] initWithE:B i:444];
printf("In Objective-C useSwiftClassInC(): m_Enum = %d, m_Int = %d\n", ue.m_Enum, ue.m_Int);
ue.m_Enum = A;
ue.m_Int = 10;
[UseEnum printUseEnum: ue];
}
And here is the Swift file:
// Swift class that uses an enum from Objective-C
class UseEnum : NSObject // NSObject inheritance is important!
{
var m_Enum : oc_enum_t
var m_Int : Int32
init(e : oc_enum_t, i : Int32)
{
m_Enum = e
m_Int = i
}
static func printUseEnum( x : UseEnum )
{
print("In Swift UseEnum::printUserEnum: m_Enum = \(x.m_Enum), m_Int = \(x.m_Int)")
}
}
// This calls an Objective-C function that does the following:
// - creates a UseEnum object
// - prints it out from Objective-C
// - modifies it
// - calls printUseEnum(), implemented in Swift, to print the object
useSwiftClassInC()
The bridging header just has
#import "oclib.h"
You have probably seen this documentation already, but if not, here it is: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
Please provide more details about your specific situation if this doesn't answer your question. Here is the output I get from the example:
In Objective-C useSwiftClassInC(): m_Enum = 1, m_Int = 444
In Swift UseEnum::printUserEnum: m_Enum = oc_enum_t(rawValue: 0), m_Int = 10
An interesting situation arises if a data type defined in Swift is used in the signature of an Objective-C function that needs to be called from Swift. Xcode won't let us import the *-Swift.h into an Objective-C header or into a bridging header. A solution is to use #class forward declaration of the Swift type. Thus, if in the above example we needed an Objective-C function that takes UseEnum as a parameter, we could have something like this in oclib.h:
...
#class UseEnum; // Forward declaration must come before UseEnum is used!
...
void useSwiftClassInC_1(UseEnum * useEnum);
...

Accessing objective-c Struct from Swift

I'm working on an ios application that has a mix of swift and obj-c code. One of my obj-c model classes defines a struct containing strings to assist in converting to a dictionary and back. I have the bridging header setup and I can access methods defined in my objective-c class in a swift class. What I can't figure out is how to access the static stuct to get at my property strings. Here is a snippet of my .h and .m files:
OrderItem.h
extern const struct OrderItemAttributes {
__unsafe_unretained NSString *created;
__unsafe_unretained NSString *created_by_id;
__unsafe_unretained NSString *device_deleted;
} OrderItemAttributes;
#interface OrderItem : NSManagedObject {}
#property (nonatomic, strong) NSDate* created;
#end
OrderItem.m
const struct OrderItemAttributes OrderItemAttributes = {
.created = #"created",
.created_by_id = #"created_by_id",
.device_deleted = #"device_deleted",
};
#implementation OrderItem
#dynamic created;
#end
I thought I would simply be able to use
OrderItem.OrderItemAttributes.created
to access the attribute strings but swift doesn't accept that syntax. Is there any way to do what I want without major changes to my objective-c code?
The variable OrderItemAttributes isn't part of the OrderItem namespace. It would be accessed directly as:
var foo: NSString = OrderItemAttributes.created.takeUnretainedValue()
The problem you're seeing with autocomplete occurs because OrderItemAttributes is ambiguous; it's both a type name and a variable name. Use different names for the struct type name and the global variable to avoid the ambiguity. E.g., add 'Struct' to the end of the type name:
extern const struct OrderItemAttributesStruct {
__unsafe_unretained NSString *created;
__unsafe_unretained NSString *created_by_id;
__unsafe_unretained NSString *device_deleted;
} OrderItemAttributes;

Swift 1.2 error on Objective-C protocol using getter

This Objective-C protocol used to work in Swift 1.1, but now errors in Swift 1.2.
Objective-C Protocol stripped down to the one problematic property:
#protocol ISomePlugin <NSObject>
#property (readonly, getter=getObjects) NSArray * objects;
#end
class SomePlugin: NSObject, ISomePlugin {
var objects: [AnyObject]! = nil
func getObjects() -> [AnyObject]! {
objects = ["Hello", "World"];
return objects;
}
}
Here is the Swift 1.2 error:
Plugin.swift:4:1: error: type 'SomePlugin' does not conform to protocol 'ISomePlugin'
class SomePlugin: NSObject, ISomePlugin {
^
__ObjC.ISomePlugin:2:13: note: protocol requires property 'objects' with type '[AnyObject]!'
#objc var objects: [AnyObject]! { get }
^
Plugin.swift:6:9: note: Objective-C method 'objects' provided by getter for 'objects' does not match the requirement's selector ('getObjects')
var objects: [AnyObject]! = nil
^
If I change the Protocol (which I cannot really do since it is from a third party) to the following, the code compiles fine.
// Plugin workaround
#protocol ISomePlugin <NSObject>
#property (readonly) NSArray * objects;
- (NSArray *) getObjects;
#end
Thanks in advance.
You can implement
#property (readonly, getter=getObjects) NSArray * objects;
as a read-only computed property with an #objc attribute
specifying the Objective-C name.
If you need a stored property as backing store
then you'll have to define that separately.
Example:
class SomePlugin: NSObject, ISomePlugin {
private var _objects: [AnyObject]! = nil
var objects: [AnyObject]! {
#objc(getObjects) get {
_objects = ["Hello", "World"];
return _objects;
}
}
}

Issue understanding "Referring to Instance Variables" from Apple guide

I am trying to understand Referring to Instance Variables from Apple guide but having issue understudying this, Apple Doc says
...When the instance variable belongs to an object that’s not the receiver, the object’s type must be made explicit to the compiler through static typing. In referring to the instance variable of a statically typed object, the structure pointer operator (->) is used.
Suppose, for example, that the Sibling class declares a statically typed object, twin, as an instance variable:
#interface Sibling : NSObject
{
Sibling *twin;
int gender;
struct features *appearance;
}
As long as the instance variables of the statically typed object are within the scope of the class (as they are here because twin is typed to the same class), a Sibling method can set them directly:
- makeIdenticalTwin
{
if ( !twin )
{
twin = [[Sibling alloc] init];
twin->gender = gender;
twin->appearance = appearance;
}
return twin;
}
Referring to instance variable means, accessing the class instance vars
For example:
#interface ClassA : NSObject
{
int value;
}
- (void) setValue:(int) val;
#implementation ClassA
- (void) setValue:(int) val
{
//here you could access class a value variable like this
value = val;
}
Now accessing other classes variables
take for example this class
#interface ClassB : ClassA
{
ClassA aClass;
}
- (void) setValueInAClass:(int) val;
#implementation ClassB
- (void) setValueInAClass:(int) val
{
//class b could access variables from class a like this
aClass->value = val;
}
Please note that this is very un recommended to do, using the "->" breaks the encapsulation of class a, so dont in 99% of the cases referring to class variables using the "->" is a mistake

Structure as a class member in Objective C

Is it possible a structure as a class member in objective C? If yes how can I assign values to that structure from another class?
Yes, you can. You either just expose the structure as a property (in which case you have to set/get the whole thing) or you write custom accessors that walk into the fields of the strucutre.
For a concrete example, CGRect is a structure (though it is hidden by a typdef), which means the frame property of UIView get and set a structure.
In other words:
CGRect myFrame = CGRectMake(0,0,320,480); //CGRect is a struct
myView.frame = myFrmae; //Setting a struct
You just use dot notation to assign and access the values. You can also use -> if you have a pointer to a struct.
typedef struct {
int a;
double b;
} SomeType;
// Define some class which uses SomeType
SomeType myVar;
myVar.a = 1;
myVar.b = 1.0;
SomeType* myPtr = &myVar;
NSLog (#"%i", myPtr->a);
// This works...
SomeType mySecondVar = myVar;
// But you have to be careful in cases where you have pointers rather than values.
// So this wouldn't work if either element was a C string or an array.
Yes and there is an easy way to access that struct using Objective-C 2.0 Properties. Consider the following struct from Stephens post.
typedef struct {
int a;
double b;
} SomeType;
In your .h file you would declare the member in your #interface
#interface AClass : NSObject{
SomeType member;
}
#property SomeType member;
#end
Remember that if you choose to go with pointers here you will need to manage your own memory.
And in your #implementation (your .m file) don't forget add a #synthesize
#implementation AClass
#synthesize member;
#end
I hope this helps.