Serializing a Swift class to JSON using J2ObjC and GSON library - ios

I'm very new to iOS, moving from Android development.
We have an Android application which has several libraries which we're using J2ObjC to translate into Objective C.
I've been gradually bringing over the libraries and so far, so good.
However, after translating Google's GSON library I have an issue where if I try and use the translated method toJsonWithId I come across problems:
let gson = ComGoogleGsonGson()
let swiftTest = GsonSwiftTest()
swiftTest.name = "Ricky"
print(gson.toJsonWithId(swiftTest))
I receive the following error:
libc++abi.dylib: terminating with uncaught exception of type
JavaLangAssertionError
Further it shows:
Terminating app due to uncaught exception 'JavaLangAssertionError',
reason: 'unknown Java type encoding'
My Swift class is:
import Foundation
#objc
public class GsonSwiftTest : NSObject {
var name:String?
}
If I instead use an Objective C class in my Swift project, add it to the bridging header and use the Objective C class it works fine.
I believe this is a misunderstanding on my part, but I can't find the answer as to why this won't work. Checking the J2ObjC source code shows the error is raised when the type of class can't be found.
If anyone could help explain the reasons for this issue, it'd be appreciated.
Thanks!

There's a much easier way to serialize Swift instances: use the Foundation class NSJSONSerialization directly. Here's a relevant blog posting: JSON Serialization in Swift.
The reason your test fails in Swift is that not all Swift classes extend NSObject, which j2objc maps to java.lang.Object. All Java serialization frameworks assume/require that all classes extend Object, like they do in Java.
For a cross-platform API, I recommend creating a simple serialize/unserialize interface, then implement it once for Android using GSON, and once natively using NSJSONSerialization. Swift is evolving rapidly, so if a better serialization mechanism becomes available, your project can easily take advantage of it without affecting the Android port.

Related

NSKeyedUnarchiver issue when moving model to framework [duplicate]

This question already has an answer here:
Added a custom framework, now Swift can't unarchive data
(1 answer)
Closed 2 years ago.
I have moved part of my code into a separate framework, and that framework contains a model used by the app to persist data to CoreData. Now when I try to launch the app, and it tries to restore state from CoreData, I get the following error.
2020-06-17 21:01:42.549851-0400 Project[17576:2986881] [error] fault: exception raised during multi-threaded fetch *** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (Project.Track) for key (NS.objects) because no class named "Project.Track" was found; the class needs to be defined in source code or linked in from a library (ensure the class is part of the correct target). If the class was renamed, use setClassName:forClass: to add a class translation mapping to NSKeyedUnarchiver ({
"__NSCoderInternalErrorCode" = 4864;
})
It worked as expected before splitting the code off into a separate framework. I have tried to import the framework into each class that uses CD, and I have even tried to map it to the class' new namespace using Framework.Track, but I am still getting this error. Has anyone encountered this, and if so can you share some insight into resolving the error? I appreciate any help.
I found the answer, it was as specified by the exception. I just had to set the class name using the app's namespace to the new imported class, as so:
NSKeyedUnarchiver.setClass(Track.self, forClassName: "Project.Track")
Hope that helps someone.

Hide Objective C in mixed Swift Cocoapod library

I am developing a Swift Cocoapod library which actually is a wrapper around some Objective C code.
My goal is to expose only the Swift part of the library, while making the Objective C
as private as possible. However, as the Swift part is a wrapper around the Objective C code, it needs to access it, although just internally.
I have searched and tried various approaches, but none of them worked at all.
First, I tried to address it via the use of a modulemap file. The idea was to create a Swift module called something like MyLibrary containing all the Swift code, while the Objective C code would be on the MyLibrary.Private module (I know the module would still be accessible, but this separation would be enough for me). The modulemap would look something like:
//MyLibrary.modulemap
framework module MyLibrary {
module Private {
header "MyObjectiveC.h"
export *
}
}
And adding the following line in the MyLibrary.podspec file
s.module_map = 'path/to/MyLibrary.modulemap'
However, by using this approach, even if I only import the MyLibrary module would still get access to all the Objective C classes, without having to import the MyLibrary.Private module to do so.
A second approach I tried was to make use of a private.modulemap file. So I would end up with two different modulemap files:
//MyLibrary.modulemap
framework module MyLibrary {}
//MyLibrary.private.modulemap
module MyLibrary.Private {
header "MyObjectiveC.h"
export *
}
I would then add the following line in the MyLibrary.podspec file
s.pod_target_xcconfig = { 'MODULEMAP_PRIVATE_FILE' => '$(PODS_ROOT)/MyLibrary/path/to/MyLibrary.private.modulemap' }
However, I get a failed build stating that it can not find the MyLibrary.Private module.
Is there anything I am doing wrong in these approaches? Or is there any other way to allow my library's Swift classes access the Objective C classes privately without exposing those, at least explicitly, requiring to import an specific *.Private module for it?

What should I import for GLKVector2 in Swift? [duplicate]

So I'm using a book called iOS Games by tutorials from Ray Wenderlich and trying to utilize some of the objective-C code found there to make the accelerometer control of a character in my game work. Instead of Objective-C though, I want to use Swift. I ran into an issue when trying to create a var of type GLKVector3, which represents a 3D vector. When I type in:
var raw:GLKVector3 = GLKVector3Make(irrelevant stuff)
I get the following error:
use of module GLKVector3 as type.
I have an import at the top of my swift file for GLKit:
import GLKit
Any ideas how I can get the functionality from the GLKMath files to use in my program?
Swift has added union support in version 1.2. The fields in imported unions are read-only, even if declared with var, but can be passed to and from C functions as necessary.
The release notes for Swift 1.2 imply that the fields may not be accessible at all, but they are still readable for at least the GLKit types:
Swift can now partially import C aggregates containing unions, bitfields, SIMD vector types, and other C language features that are not natively supported in Swift. The unsupported fields will not be accessible from Swift, but C and Objective-C APIs that have arguments and return values of these types can be used in Swift. This includes the Foundation NSDecimal type and the GLKit GLKVector and GLKMatrix types, among others.
With the release of beta version of Xcode 6.3/Swift 1.2 yesterday (Feb 8, 2015) it is now possible to use GLKit from Swift.
Here check my repo: https://github.com/noxytrux/SwiftGeom i actually build a whole lib for that, so you are no more forced to use GLKit or wait for Apple to implement it in swift.

How to handle exception or write custom exception class in static library?

I am creating static ios library, and want to throw system generated exception as well as custom exception with code and message to user on request failure.
User will import my header files and .a file and call static library methods.
Can somebody tell me what is the easiest and generalize way to handle exception or create own exception and throw back to user, So that user will take specific action by getting code and message.
I have go over the following links, but want to create custom NSError class or NSException class so that i can add my own error code and message, So little bit confused what to do,
How to create custom exception in objective c?
Exception handling in entire application
Please help.
Thanks & Regards,
In general, exception handling is not a safe language mechanism in Objective-C, so you should only use it for programming errors. E.g. you can use [NSException raise:NSInvalidArgumentException format:#"fooIndex out of range. Should be 0..%d, but is %d", (int)self.length, fooIndex];

Using bTouch to bind to the ArcGIS iOS SDK

I apologize for such a long message in advance, but I'm trying for detail here...
I'm working on using bTouch to create a compiled dll for referencing the ArcGIS iOS SDK.
When running bTouch using :
/Developer/MonoTouch/usr/bin/btouch libArcGIS.cs
it returns the following error
/tmp/fp2ivuh8.3gj/IncidentReportApp/AGSMutablePolygon.g.cs(39,31):
error CS0102: The type `IncidentReportApp.AGSMutablePolygon'
already contains a definition for `selAddPointToRing'
/tmp/fp2ivuh8.3gj/IncidentReportApp/AGSMutablePolygon.g.cs(38,31):
(Location of the symbol related to previous error)
/tmp/fp2ivuh8.3gj/IncidentReportApp/AGSMutablePolyline.g.cs(39,31): error CS0102:
The type `IncidentReportApp.AGSMutablePolyline'
already contains a definition for `selAddPointToPath'
/tmp/fp2ivuh8.3gj/IncidentReportApp/AGSMutablePolyline.g.cs(38,31):
(Location of the symbol related to previous error)
Compilation failed: 2 error(s), 0 warnings
I checked my cs class and neither type is referenced\invoked. I'd like to understand why this message is occuring.
I have tried to use the instructions (and downloaded) code by Al Pascual at How to use the ArcGIS iPhone SDK with MonoTouch to call the Map View, but when attempting to launch the view with the code causes a crash. When I try to debug, it locks up when adding a mapping layer. I tested this with the MKMapView, but didn't experience the same behavior.
The error means that you defined more than one method mapping the same objective-C method.
Without the source, it is hard to diagnose.
I'm doing the same thing actually, I heavily modified the old "parser" library and am working on doing it now, hopefully dropping it in the public domain.
I'm seeing a similar (and probably related) problem in the ApiDefinition, there is a class AGSGPResultLayer that derives from AGSDynamicLayer. The AGSGPResultLayer overrides a property called Credential among other and since both are defining the same property.
How should over-riden properties be handled in bTouch? I'm guessing I'm missing something in the syntax.
Use the solution I provide with the correct bindings

Resources