Property default values based on another property's value - ios

In Realm,
Is it possible to set the default value of a persisted property, based on the value of another property?
For example. I have a name property that includes UpperCase/LowerCase/Accents/etc. I want to have a tokenizedName that transforms the name property into a more simple string (all undercase, no accents).

You could easily do this with derived properties:
class Person: Object {
var name: String {
get {
return _name
}
set {
_name = newValue
// perform tokenization...
tokenizedName = _name.lowercaseString
}
}
private dynamic var _name = ""
dynamic var tokenizedName = ""
override class func ignoredProperties() -> [String] { return ["name"] }
}
Here _name and tokenizedName are properties persisted in Realm, while name is ignored. Every time you read from name, you're just from its underlying storage. Every time you write to name, you set its backing storage and update the tokenized version.
Edit: In Objective-C
#interface Person : RLMObject
#property (nonatomic, copy) NSString *name;
#property NSString *_name;
#property NSString *tokenizedName;
#end
#implementation Person
- (NSString *)name {
return self._name;
}
- (void)setName:(NSString *)name {
self._name = name;
// perform tokenization...
self.tokenizedName = name.lowercaseString;
}
+ (NSArray<NSString *> *)ignoredProperties {
return #[#"name"];
}
#end

Related

Generic enum type in objective-c

I have two objective-c classes HondaDealerShip and FordDealerShip. They both contain similar properties and methods, so I want to define a common protocol DealerShip and do some polymorphism.
The problem is this DealerShip needs to contain generic enum type properties, so that HondaDealerShip and FordDealerShip can have different concrete enum types.
So I want something like this,
#protocol DealerShip
#property (nonatomic, readonly) enum location;
-(void)printPriceOfModel:(enum)vehicleModel;
#end
typedef NS_ENUM(NSInteger, HondaLocation) {
HondaLocationSouthEast,
HondaLocationNorthWest
}
typedef NS_ENUM(NSInteger, HondaModel) {
Accord,
Civic
}
#interface HondaDealerShip: NSObject<DealerShip>
#property (nonatomic, readonly) HondaLocation location;
- (void)printPriceOfModel:(HondaModel)vehicleModel {
//print price here
}
#end
typedef NS_ENUM(NSInteger, FordLocation) {
FordLocationEast,
FordLocationWest
}
typedef NS_ENUM(NSInteger, FordModel) {
Mustang,
Focus
}
#interface FordDealerShip: NSObject<DealerShip>
#property (nonatomic, readonly) FordLocation location;
- (void)printPriceOfModel:(FordModel)vehicleModel {
//print price here
}
#end
If I have to do this in swift, I could use protocols with associated types like below
protocol DealerShip {
associatedtype Location
associatedtype Model
var location: Location { get }
func printPriceOfModel(model : Model)
}
enum HondaLocation: Int {
case sountEast
case northWest
}
enum HondaModel: Int {
case accord
case civic
}
struct HondaDealerShip: DealerShip {
var location: HondaLocation
func printPriceOfModel(model: HondaModel) {
//print
}
}
//same for FordDealerShip
can I do similar in objective-c?.
Nope, you cannot use enum with associated types in objective c. The language does not support it.

After binding using Objective Sharpie Protocol Methods are not getting invoked in xamarin.iOS

I have few issues with Binding using Objective sharpie.I am binding IndoorAtlas iOS native sdk with Xamarin.ios.
Issue is while Implementing Protocols methods as those are not getting invoked. Do we need to handle it in special way?
I am attaching API defination file and Implementation file.
// #protocol IALocationManagerDelegate
[Protocol, Model]
[BaseType(typeof(NSObject))]
interface IALocationManagerDelegate
{
// #optional -(void)indoorLocationManager:(IALocationManager *
_Nonnull)manager didUpdateLocations:(NSArray * _Nonnull)locations;
[Export("indoorLocationManager:didUpdateLocations:")]
void DidUpdateLocations(IALocationManager manager, IALocation[] locations);
// #optional -(void)indoorLocationManager:(IALocationManager *
_Nonnull)manager didEnterRegion:(IARegion * _Nonnull)region;
[Export("indoorLocationManager:didEnterRegion:")]
void DidEnterRegion(IALocationManager manager, IARegion region);
}
// #interface IALocationManager : NSObject
[BaseType(typeof(NSObject))]
interface IALocationManager
{
[Wrap("WeakDelegate")]
[NullAllowed]
IALocationManagerDelegate Delegate { get; set; }
// #property (readwrite, nonatomic, weak) id<IALocationManagerDelegate>
_Nullable delegate;
[NullAllowed, Export("delegate", ArgumentSemantic.Weak)]
NSObject WeakDelegate { get; set; }
}
////ViewController --Calling delegate methods
[Export("indoorLocationManager:didUpdateLocations:")]
public void DidUpdateLocations(IALocationManager manager , IALocation[] locations)
{
IALocation loc = locations[locations.Length - 1];
if (mFloorPlan != null)
{
CoreGraphics.CGPoint cg = mFloorPlan.CoordinateToPoint(loc.Location.Coordinate);
this.map.Center = cg;
}
}
[Export("indoorLocationManager:didEnterRegion:")]
public void DidEnterRegion(IALocationManager manager, IARegion region)
{
if (region.Type != ia_region_type.FloorPlan)
Console.WriteLine("Region Changed to {0} " + region.Identifier);
else
{
FetchFloorPlan();
}
}
Don't forget to assign the viewcontroller to the weak delegate.
IALocationManager manager = new IALocationManager();
manager.WeakDelegate = this;

Swift: Check if datatype can be converted to Double

I want to check if the received data from a MySQL-database can be converted to Double and if that's possible I want to append it to an array.
From another question i got the following code:
extension String {
struct NumberFormatter {
static let instance = NSNumberFormatter()
}
var doubleValue:Double? {
return NumberFormatter.instance.numberFromString(self)?.doubleValue
}
var integerValue:Int? {
return NumberFormatter.instance.numberFromString(self)?.integerValue
}
}
Here's my concerned Code (which is in a for-loop):
if let value = datas[i].puls.doubleValue {
pulsWerte.append(value)
print(datas[i].puls)
}else {
badIndex.append(i)
continue
}
In case an entry of my database is NULL, my program should proceed in the else-branch. But if I test such a case I end up with a runtime-error and the following two messages:
-[NSNull length]: unrecognized selector sent to instance 0x1451238
&
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull length]: unrecognized selector sent to instance 0x1451238'
Does anyone know my mistake?
UPDATE
This is how my datas-array gets created:
For downloading and allocating the data I'm using Objectiv-C.
In my Data.h-file I create my Data-class.
#interface Data : NSObject
#property (nonatomic, strong) NSString *sozialversicherungsnummer;
#property (nonatomic, strong) NSString *messzeitpunkt;
#property (nonatomic, strong) NSString *puls;
#property (nonatomic, strong) NSString *sauerstoffgehalt;
#end
And in my HomeModel.m I create a NSMutableArray named "_data". After my download is finished this array gets filled as follows:
for (int i = 0; i < jsonArray.count; i++)
{
NSDictionary *jsonElement = jsonArray[i];
// Create a new data object and set its props to JsonElement properties
Data *newData = [[Data alloc] init];
newData.sozialversicherungsnummer = jsonElement[#"Sozialversicherungsnummer"];
newData.messzeitpunkt = jsonElement[#"Messzeitpunkt"];
newData.puls = jsonElement[#"Puls"];
newData.sauerstoffgehalt = jsonElement[#"Sauerstoffgehalt"];
// Add this question to the locations array
[_data addObject:newData];
}
When this step is completed I get this "_data"-array under the name of a parameter called "items" by a function called "itemsDownloaded".
And now I call this function in my Swift-file and here I'm able to typecast the downloaded "items" as "Data" (my self created class).
func itemsDownloaded(items: [AnyObject]!) {
let datas = items as! [Data]
.
.
.
First of all you can define the following protocol.
DoubleConvertible
protocol DoubleConvertible {
func toDouble() -> Double?
}
Making String, Int and Double conform DoubleConvertible
Next, for each type that you want to be convertible to Double you need to make that type conform to DoubleConvertible.
Let's do it for String
extension String: DoubleConvertible {
func toDouble() -> Double? {
return Double(self)
}
}
and Int
extension Int: DoubleConvertible {
func toDouble() -> Double? {
return Double(self)
}
}
and ... well Double
extension Double: DoubleConvertible {
func toDouble() -> Double? {
return self
}
}
From [Any] to [Double]
Now given a list of values of several different types
let list: [Any?] = ["123", nil, "Hello", 456, true, 789.1]
We can easily convert it to a list of Double.
let listOfDouble = list
.flatMap { $0 as? DoubleConvertible }
.flatMap { $0.toDouble() }
listOfDouble // [123.0, 456.0, 789.1]
Your implementation of doubleValue:Double? assumes that self is a String.
var doubleValue:Double? {
return NumberFormatter.instance.numberFromString(self)?.doubleValue
}
The datas[i].puls is created by an Objective-C JSON Parser which produces in the case of NULL an instance of NSNull but you expect to set nil.
The easiest way is to check jsonElement[#"Puls"] for NSNull and then set newData.puls to NULL:
id puls = jsonElement[#"Puls"];
if puls == [NSNull null] {
newData.puls = null;
} else {
newData.puls = puls;
}

replace 'Class' in swift

I am moving from objective-C to Swift.
The header file was:
#interface RegisterType : NSObject
{
Class type;
NSString *typeName;
NSString *namespace;
int typeId;
}
#property (nonatomic,retain) Class type;
#property (nonatomic,retain) NSString *typeName;
#property (nonatomic,retain) NSString *namespace;
#property (nonatomic) int typeId;
#end
and the implementation was:
#implementation RegisterType
#synthesize type;
#synthesize typeName;
#synthesize namespace;
#synthesize typeId;
Now is Swift my code is:
class RegisterType {
//var type: AnyClass
var typeName: String = ""
var namespace: String = ""
var typeId: Int = 0
}
My main is problem is that I want to replace the generic type 'Class' that I used in objective-C. How do I replace it in Swift? Do I need an init method?
If I understand your question correctly, I would do something like this:
class RegisterType: NSObject {
override init() {
super.init()
self.type = self.classForCoder
}
var type: AnyClass?
var typeName: String = ""
var namespace: String = ""
var typeId: Int = 0
}
let xx = RegisterType()
println(xx.type) // prints "RegisterType"

convert struct to objective c array or class

I m new for IOS. I have some source code for OS X and java. I was trying to convert to IOS.
In OS X, I have the following.
struct _NoteData {
int number; /** The Midi note number, used to determine the color */
WhiteNote *whitenote; /** The white note location to draw */
NoteDuration duration; /** The duration of the note */
BOOL leftside; /** Whether to draw note to the left or right of the stem */
int accid; /** Used to create the AccidSymbols for the chord */
};
typedef struct _NoteData NoteData;
#interface ChordSymbol : NSObject <MusicSymbol> {
_NoteData notedata[20];/** The notes to draw */
}
_NoteData is like an array and class here. number, whitenote,duration..are instance variable for _noteData.
I was trying to change struct to objective c class:
#interface _NoteData:NSObject{
#property NSInteger number_color;
#property WhiteNote *whitenote;
#property NoteDuration duration;
#property BOOL leftside;
#property NSInteger accid;
};
#interface ChordSymbol : NSObject <MusicSymbol> {
_NoteData notedata[20];/** The notes to draw */
}
In my .m file, it has
+(BOOL)notesOverlap:(_NoteData*)notedata withStart:(int)start andEnd:(int)end {
for (int i = start; i < end; i++) {
if (!notedata[i].leftside) {
return YES;
}
}
return NO;
}
!notedata[i] throw error expected method to read array element. I understand _NoteData is a class, not an array. What should I change?
In java:
private NoteData[] notedata;
NoteData is a class, and notedata is an array which store NoteData.
Same method in java
private static boolean NotesOverlap(NoteData[] notedata, int start, int end) {
for (int i = start; i < end; i++) {
if (!notedata[i].leftside) {
return true;
}
}
return false;
}
I feel all I need is to declare an array with _NoteData object. How can I do that?
Objective-C is a superset of C, so you can use C struct in Objective-C code. You can keep your code in the first paragraph. You need to move the function declaration in ChordSymbol class's header file.
+(BOOL)notesOverlap:(NoteData*)notedata withStart:(int)start andEnd:(int)end;
In another Objective-C class's implementation file, call the Class function like this.
NoteData y[] = {
{ .leftside = YES },
{ .leftside = YES },
{ .leftside = YES },
{ .leftside = YES }
};
BOOL result = [ChordSymbol notesOverlap:y withStart:0 andEnd:3];
NSLog(#"%d",result);
Edit
You can use NSArray for this purpose. You create an array and populate its data with NoteData objects.
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:20];
NoteData *data1 = [[NoteData alloc] init];
data1.number_color = 1;
[array addObject:data1];
Then you should change (_NoteData*)notedata to (NSArray*)array, and it should work.

Resources