Is there any way to exclude a data member from a class that is being persisted by the Backendless Data Service? (Like a java annotation, for example.)
There are cases where there is information stored on the data object that I do not want persisted on the server and I cannot find a way to annotate or specify what is persisted and not persisted.
Hi Tim,
With Java you have the following options:
- For fields you can use the transient declaration.
For Java bean properties you can use the @ExcludeProperty annotation as shown below:
[/code]
There is also a way to list multiple bean properties in a single annotation:
@ExcludeProperties( propertyNames = { "foo", "bar" } )
The @ExcludeProperty annotation is in the weborb.service.ExcludeProperty package.
I will find out about available options in our Obj-C support and will let you know.
Regards,
Mark
The annotation worked great for Android. Is similar functionality possible in iOS? It would be ideal if the models on iOS and Android could mirror each other.
Hi Tim,
Unfortunately, there is no similar support for iOS. The recommended approach is to mark your field private and have public accessor methods (the Java bean style serialization does not apply in iOS).
Regards,
Mark
Hi Mark,
Sorry for waking up an old thread but I was in fact looking for an answer to that same question. Can you please elaborate on your answer, it’s not clear to me how to create private property in Objective-C since there is no such concept in the language.
Thanks!
Hi Emmanuel,
Here is an example of the “private” property - ‘beacons’.
Retailer.h:
@interface Retailer : NSObject
@property (nonatomic, strong) NSString *objectId;
@property (nonatomic, strong) NSString *company;
@property (nonatomic, strong) NSMutableDictionary *location;
@end
Retailer.m:
@interface Retailer ()
@property (nonatomic, strong) NSMutableDictionary *beacons;
@end
@implementation Retailer
-(NSString *)description {
return [NSString stringWithFormat:@"<Retailer> [%@] %@\nlocations:%@\nbeacons:%@", self.objectId, self.company, self.location, self.beacons];
}
@end
The ‘beacons’ property is not being persisted by the Data Service.
Regards,
Slava
Hi Slava,
Unfortunately this doesn’t work. The “private” data member is still saved to the DB.
I’ve tried with a NSString though, not a NSMutableDictionary, but I believe that in this case a new relation would be created to the table “beacon” in this case (depending on the type of objects you hold in the beacons variable".
Thanks.
Hi again,
I’d like to share my (convoluted) solution for you to consider and improve on.
Say I have a class called File as such:
@interface File : NSObject
@property (nonatomic, strong) NSString *mime;
@property (nonatomic, strong) NSString *url;
@property (nonatomic, strong) NSString *objectId;
@property (nonatomic, strong) NSString *ownerId;
@property (nonatomic, strong) NSDate *created;
@property (nonatomic, strong) NSDate *updated;
+ (File *)fileWithName:(NSString *)name data:(NSData *)data;
+ (File *)fileWithName:(NSString *)name mime:(NSString *)mime data:(NSData *)data;
- (NSString *)name;
- (NSData *)getData;
- (BOOL)isUploaded;
- (void)upload:(void(^)(NSString *url))successBlock error:(void(^)(Fault *fault))errorBlock;
@end
I don’t want to store the ‘name’ and ‘data’ properties to the DB so I create a new class in the .m file called FileData:
@interface FileData : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) NSData *data;
@property (nonatomic, assign) BOOL uploaded;
+ (FileData *)fileData:(NSString *)name data:(NSData *)data;
@end
I also declare a static MapTable like so:
static NSMapTable *fileData;
Then in the implementation of class File I create the MapTable fileData and use it to store and retrieve the private data:
@implementation File
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
fileData = [NSMapTable weakToStrongObjectsMapTable];
});
}
+ (File *)fileWithName:(NSString *)name data:(NSData *)data {
return [self fileWithName:name mime:@"" data:data];
}
+ (File *)fileWithName:(NSString *)name mime:(NSString *)mime data:(NSData *)data {
File *file = [File new];
if (file) {
FileLocalData *fileLocalData = [FileLocalData fileData:name data:data];
[fileData setObject:fileLocalData forKey:file];
file.mime = mime;
}
return file;
}
- (void)dealloc {
[fileData removeObjectForKey:self];
}
- (NSString *)name {
FileLocalData *fileLocalData = [fileData objectForKey:self];
return fileLocalData.name;
}
- (NSData *)getData {
FileLocalData *fileLocalData = [fileData objectForKey:self];
return fileLocalData.data;
}
- (BOOL)isUploaded {
FileLocalData *fileLocalData = [fileData objectForKey:self];
return fileLocalData ? fileLocalData.uploaded : YES;
}
- (void)upload:(void(^)(NSString *url))successBlock error:(void(^)(Fault *fault))errorBlock {
[backendless.fileService
upload:[self name]
content:[self getData]
response:^(BackendlessFile *file) {
successBlock(file.fileURL);
}
error:^(Fault *fault) {
errorBlock(fault);
}];
}
@end
Hi Emmanuel,
I think the simplest way to solve this issue is to use private variables instead properties. These variables can be set, changed or removed via the public methods.
I’ve made the appropriate correction in my example:
Retailer.h
@interface Retailer : NSObject
@property (nonatomic, strong) NSString *objectId;
@property (nonatomic, strong) NSString *company;
@property (nonatomic, strong) GeoPoint *location;
@end
Retailer.m
@interface Retailer () {
NSMutableArray *beacons;
NSData *data;
}
@end
@implementation Retailer
-(NSString *)description {
return [NSString stringWithFormat:@"<Retailer> [%@] %@\nlocation:%@\nbeacons:%@\ndata:%@", self.objectId, self.company, self.location, beacons, data];
}
@end
Hi Slava,
I see, I’ll try that, thanks!
I try to figure out how to use this in swift.
I want to build objects I can later convert to an object like MKAnnotations for the use in MKMapKit.
Unfortunately the iOS SDK asks the server for the property that doesn’t exists on the table at backendless. So I want to ignore this property. Is there any workaround for swift?
import Foundation
import MapKit
class Story: NSObject {
dynamic var objectId: String?
// The story's title
dynamic var title: String?
// The text to a story written by the user
dynamic var text: String?
// The geopoint of this story
dynamic var location: GeoPoint?
// Relationships
// to-many: A story can have more than one category
dynamic var categories: [Category] = []
// to-many: A story has one or more figures
dynamic var figures: [Figure] = []
}
extension Story: MKAnnotation {
var coordinate: CLLocationCoordinate2D {
return CLLocationCoordinate2D(latitude: location?.longitude as! Double, longitude: location?.latitude as! Double)
}
}
This is how it looks right now. The property to ignore is “coordinate” but needed in this class since it is required by MKAnnotation.
Hi Lennart,
is the goal to make sure the “coordinate” property is ignored when you save instances of Story on the server?
Regards,
Mark
No I don’t wanna save it on the servers. It’s just a entity I need to build a view for on the App.