Objective-C Swift interoperability with Realm - ios

I'm adding new functionality to an app written in Objective-C with Swift. The new features require a data base so I'm using Realm-Swift. The problem is that the models that have relationships e.g. dynamic var points = List<Point>() don't translate to Objective-C on the {Project}-Swift.h file. I get the error: Type name requires a specifier or qualifier on the line #property (nonatomic) /* List<Point> */ points;
Does anybody know a workaround for this problem?

If you need Objective-C interop, your best bet is to continue using Realm Objective-c. Since List is a generic type, it can't be represented in ObjC at all.

Related

How to access a List property of a swift class from an Objective C class

I have this swift model class (using Realm) that has a simple String property and a List of strings. I can easily access the string property from an Objective-C class, but it doesn't seem to work when I try to access the List property.
Code:
class MyClass: Object, Mappable {
dynamic var stringProperty: String?
let listOfStrings = List<StringValue>()
}
I tried creating a getter method that returns a simple array from the List property, but I wonder if there is a better way.
One of the first things that the Realm Swift documentation says is:
If you’re looking to use Realm from Objective‑C, or from mixed Objective‑C & Swift apps, please see Realm Objective‑C instead. The Realm Objective‑C and Realm Swift APIs are not interoperable and using them together is not supported.
There is some limited, unofficial support for interoperability with Objective-C available that may help you, but it's really intended for only very narrow use cases (primarily to allow writing frameworks that wish to support models written in both Realm Objective-C and Realm Swift). The general advice is that if you want to access your Realm models from both Objective-C and Swift, use Realm Objective-C.

Xcode Parse Issue Expected '>', Expected ')' [duplicate]

I'm new to Mac/iPhone programming and Objective-C. In C# and Java we have "generics", collection classes whose members can only be of the type declared. For example, in C#
Dictionary<int, MyCustomObject>
can only contain keys that are integers and values that are of type MyCustomObject. Does a similar mechanism exist in Objective-C?
In Xcode 7, Apple has introduced 'Lightweight Generics' to Objective-C. In Objective-C, they will generate compiler warnings if there is a type mismatch.
NSArray<NSString*>* arr = #[#"str"];
NSString* string = [arr objectAtIndex:0];
NSNumber* number = [arr objectAtIndex:0]; // Warning: Incompatible pointer types initializing 'NSNumber *' with an expression of type 'NSString *'
And in Swift code, they will produce a compiler error:
var str: String = arr[0]
var num: Int = arr[0] //Error 'String' is not convertible to 'Int'
Lightweight Generics are intended to be used with NSArray, NSDictionary and NSSet, but you can also add them to your own classes:
#interface GenericsTest<__covariant T> : NSObject
-(void)genericMethod:(T)object;
#end
#implementation GenericsTest
-(void)genericMethod:(id)object {}
#end
Objective-C will behave like it did before with compiler warnings.
GenericsTest<NSString*>* test = [GenericsTest new];
[test genericMethod:#"string"];
[test genericMethod:#1]; // Warning: Incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'
but Swift will ignore the Generic information completely. (No longer true in Swift 3+.)
var test = GenericsTest<String>() //Error: Cannot specialize non-generic type 'GenericsTest'
Aside from than these Foundation collection classes, Objective-C lightweight generics are ignored by Swift. Any other types using lightweight generics are imported into Swift as if they were unparameterized.
Interacting with Objective-C APIs
This answer is outdated but remains for historical value. As of Xcode 7, Connor's answer from Jun 8 '15 is more accurate.
No, there are no generics in Objective-C unless you want to use C++ templates in your own custom collection classes (which I strongly discourage).
Objective-C has dynamic typing as a feature, which means that the runtime doesn't care about the type of an object since all objects can receive messages. When you add an object to a built-in collection, they are just treated as if they were type id. But don't worry, just send messages to those objects like normal; it will work fine (unless of course one or more of the objects in the collection don't respond to the message you are sending).
Generics are needed in languages such as Java and C# because they are strong, statically typed languages. Totally different ballgame than Objective-C's dynamic typing feature.
No, but to make it clearer you can comment it with the type of object you want to store, I've seen this done a few times when you need to write something in Java 1.4 nowadays) e.g.:
NSMutableArray* /*<TypeA>*/ arrayName = ....
or
NSDictionary* /*<TypeA, TypeB>*/ dictionaryName = ...
This was released in Xcode 7 (finally!)
Note that in Objective C code, it's just a compile-time check; there will be no run-time error just for putting the wrong type into a collection or assigning to a typed property.
Declare:
#interface FooClass <T> : NSObject
#property (nonatomic) T prop;
#end
Use:
FooClass<NSString *> *foo = [[FooClass alloc] init];
NSArray<FooClass<NSString *> *> *fooAry = [NSArray array];
Be careful about those *s.
There are no generics in Objective-C.
From the Docs
Arrays are ordered collections of objects. Cocoa provides several array classes, NSArray, NSMutableArray (a subclass of NSArray), and NSPointerArray.
Apple has added generics to ObjC in XCode 7:
#property NSArray<NSDate *>* dates;
- (NSArray<NSDate *> *)datesBeforeDate:(NSDate *)date;
- (void)addDatesParsedFromTimestamps:(NSArray<NSString *> *)timestamps;
see here:
https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6-ID61
Generic NSArrays can be realized by subclassing NSArray, and redefining all provided methods with more restrictive ones. For example,
- (id)objectAtIndex:(NSUInteger)index
would have to be redefined in
#interface NSStringArray : NSArray
as
- (NSString *)objectAtIndex:(NSUInteger)index
for an NSArray to contain only NSStrings.
The created subclass can be used as a drop-in replacement and brings many useful features: compiler warnings, property access, better code creation and -completion in Xcode. All these are compile-time features, there is no need to redefine the actual implementation - NSArray's methods can still be used.
It's possible to automate this and boil it down to only two statements, which brings it close to languages that support generics. I've created an automation with WMGenericCollection, where templates are provided as C Preprocessor Macros.
After importing the header file containing the macro, you can create a generic NSArray with two statements: one for the interface and one for the implementation. You only need to provide the data type you want to store and names for your subclasses. WMGenericCollection provides such templates for NSArray, NSDictionary and NSSet, as well as their mutable counterparts.
An example: List<int> could be realized by a custom class called NumberArray, which is created with the following statement:
WMGENERICARRAY_INTERFACE(NSNumber *, // type of the value class
// generated class names
NumberArray, MutableNumberArray)
Once you've created NumberArray, you can use it everywhere in your project. It lacks the syntax of <int>, but you can choose your own naming scheme to label these as classes as templates.
Take a look at:
https://github.com/tomersh/Objective-C-Generics
It appears to be a sort of poor-man's generics, by repurposing the protocol checking mechanism.
Now dreams come true - there are Generics in Objective-C since today (thanks, WWDC).
It's not a joke - on official page of Swift:
New syntax features let you write more expressive code while improving consistency across the language. The SDKs have employed new Objective-C features such as generics and nullability annotation to make Swift code even cleaner and safer. Here is just a sampling of Swift 2.0 enhancements.
And image that proofs this:
Just want to jump in here. I've written a blog post over here about Generics.
The thing I want to contribute is that Generics can be added to any class, not just the collection classes as Apple indicates.
I've successfully added then to a variety of classes as they work exactly the same as Apple's collections do. ie. compile time checking, code completion, enabling the removal of casts, etc.
Enjoy.
The Collections classes provided by Apple and GNUStep frameworks are semi-generic in that they assume that they are given objects, some that are sortable and some that respond to certain messages. For primitives like floats, ints, etc, all the C arrays structure is intact and can be used, and there are special wrapper objects for them for use in the general collection classes (eg NSNumber).
In addition, a Collection class may be sub-classed (or specifically modified via categories) to accept objects of any type, but you have to write all the type-handling code yourself.
Messages may be sent to any object but should return null if it is inappropriate for the object, or the message should be forwarded to an appropriate object. True type errors should be caught at compile-time, not at run-time. At run-time they should be handled or ignored.
Finally, Objc provides run-time reflection facilities to handle tricky cases and message response, specific type, and services can be checked on an object before it is sent a message or put into an inappropriate collection.
Beware that disparate libraries and frameworks adopt different conventions as to how their objects behave when sent messages they do not have code responses for, so RTFM. Other than toy programs and debugging builds, most programs should not have to crash unless they really screw up and try to write bad data to memory or disk, perform illegal operations (eg divide by zero, but you can catch that too), or access off-limits system resources.
The dynamism and run-time of Objective-C allows for things to fail gracefully and should be built in to your code.
(HINT) if yo are having trouble with genericity in your functions, try some specificity. Write the functions over with specific types and let the runtime select (thats why they are called selectors!) the appropriate member-function at run-time.
Example:
-(id) sort (id) obj; // too generic. catches all.
// better
-(id) sort: (EasilySortableCollection*) esc;
-(id) sort: (HardToSortCollection*) hsc;
...
[Sorter sort: MyEasyColl];
[Sorter sort: MyHardColl];

Objective-C: NSArray of Custom Class?

I am trying to learn iOS, I come from Java background where we can have lists/arrays of specific classes like
List<String> l = new ArrayList<>();
List<MyClass> l = new ArrayList<>();
Looking at Objective-C, I can make use of NSArray class to make immutable arrays, but how do I specify that this NSArrray is strictly of type MyClass?
Now Xcode 7 supports some kind of generics for standard collections(e.g. NSArrays). So you can make an array and provide kind of storing objects like this:
NSArray<NSString*> *myArrayOfStrings;
As far as I know, there isn't a built-in mechanism for specifying the type of objects put into NSArrays in Objective-C, but it looks like Swift does what you're looking for if that helps at all:
https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-XID_172
On a slightly related note, there's a decent write-up here about enforcing inserting objects of only a certain type into a subclassed NSMutableArray and throwing exceptions if trying to insert the wrong object types:
NSMutableArray - force the array to hold specific object type only
Sadly there are no generics in Objective-C.

How to create an ObjC function outside a class in Xcode?

I am new to Obj-C and to Xcode. I have been surfing different tutorials for a few days now but there is one question I can't get straight:
I want to write a function to generate a dictionary from a long string before parsing the information to the rest of my iOS app. I imagine a small function on the side would do and I don't see how to justify defining a class with .h and .m files.
If I want to write a small function in Obj-C (and not C) in Xcode outside of a class, how do I do it?
Thank you!
Apart from just creating a C function somewhere, you could also add a category to NSString, which would probably be more in keeping with the Objective-C philosophy. That would make it possible to perform the operation on any NSString in your program.
Note, however, that the overhead is pretty much the same as creating a class, although that should not deter you from using this approach.
Use plain C methods, for example:
// .h file
NSNumber *sum(NSNumber *x, NSNumber *y);
// .m file
NSNumber *sum(NSNumber *x, NSNumber *y) {
return #(x.intValue + y.intValue);
}
Objective C does not have functions, it only has methods.
If you want to write function use plain C.

Error using scalar in managed object

I have some code in an app that creates a CoreData managed object. In this code, I use the following line to set a property:
theAuthor.authorID = 1;
The property is declared like this in the managed object header:
#property (nonatomic) uint32_t authorID;
In iOS 5 it works fine, but when I debug in iOS 4.3, I get this error:
Property 'authorID' is a scalar type on class 'Author'. Cannot generate a setter method for it.
Why am I getting this error in 4.3, but not in 5? Should I be avoiding scalar properties? I came to Obj-C from C, so I prefer to work with scalars when I can, as it feels more optimised.
Would I be better implementing the getters and setters or changing my code to use NSInteger or NSNumber instead?
See here for information on using scalar attributes in core data. (By the way, NSInteger is a scalar). Listing 3 is the particular one you are interested in. Basically, you need to write your own accessor for it, but it's not difficult.
As of iOS5, you can use scalar properties in core data. This can be achieved by ticking the appropriate box when generating your managed object subclasses from the data model.

Resources