Const/ref problem in D - constants

I'm trying to implement my own range in D, and I'm having trouble with its .front() method.
Edit:
I need the return value to be by ref.
If I make it const, then the returned object will be a copy, which is not what I want.
If I don't make it const, then I can't use .front on a const copy of my range at all.
How do I solve this?
struct MyRange(T)
{
T[] buf;
#property ref T front() { return this.buf[0]; } // No error, but not const
#property ref T front() const { return this.buf[0]; } // Errors
#property T front() const { return this.buf[0]; } // No error, but a copy
// Can't have all three
}

Try this:
struct MyRange(T)
{
T[] buf;
#property ref T front() { return this.buf[0]; }
#property ref const(T) front() const { return this.buf[0]; }
}
The problem in your example is that you made front const but not the value being returned, and the compiler won't let you escape a mutable reference to const data like that.
Now, I would point out that in general, you shouldn't expect const ranges to work very well. By their very nature, they need to be mutable to iterate over them (since you can't call popFront on a const range), so you're not going to be able to do much beyond using front and empty with a const range. The situation wouldn't be as bad if you could implicitly convert a const range to a tail-const range, but that only works with arrays, and no one has figured out a good way to do that with general ranges yet. So unfortunately, const ranges are essentially useless at this point.

what if you create a separate setter for front:
#property T front() const { return this.buf[0]; }//const
#property void front(T t) { this.buf[0]=t; }//allows assign when needed
is this within what you need?

Related

Strange error message when assigning Swift function with arguments to Objective-C property

I would like to set some properties of an Objective-C class instance to some Swift functions and I am getting an error that I do not understand, maybe something with the types is wrong:
Objective-C:
#interface MyWrapper : NSObject
#property (nonatomic) void(*f1)();
#property (nonatomic) void(*f2)(void*);
#end
Swift:
func saySomething1() {
print("Something 1")
}
func saySomething2(buf:UnsafeRawPointer) {
print("Something 2")
}
let x = MyWrapper()
x.f1 = saySomething1 // OK
x.f2 = saySomething2 // error: Cannot assign to property: 'x' is a 'let' constant
Changing let to var does not help (same error message).
The issue is not the mutability of the variable x (it is a class type, anyway), but rather of the parameter for f2. Use UnsafeMutableRawPointer, rather than UnsafeRawPointer.
FWIW, if you are unsure of the parameter type, you can open the assistant editor and then look at the generated Swift interface:
You access this from the jump bar in the assistant editor:
Or you can use a closure and type inference can tell you what type the parameter is:

Getter computed property vs. variable that returns a value

Is there a difference between a getter computed property and variable that returns a value? E.g. is there a difference between the following two variables?
var NUMBER_OF_ELEMENTS1: Int {
return sampleArray.count
}
var NUMBER_OF_ELEMENTS2: Int {
get {
return sampleArray.count
}
}
A computer property with getter and setter has this form:
var computedProperty: Int {
get {
return something // Implementation can be something more complicated than this
}
set {
something = newValue // Implementation can be something more complicated than this
}
}
In some cases a setter is not needed, so the computed property is declared as:
var computedProperty: Int {
get {
return something // Implementation can be something more complicated than this
}
}
Note that a computed property must always have a getter - so it's not possible to declare one with a setter only.
Since it frequently happens that computed properties have a getter only, Swift let us simplify their implementation by omitting the get block, making the code simpler to write and easier to read:
var computedProperty: Int {
return something // Implementation can be something more complicated than this
}
Semantically there's no difference between the 2 versions, so whichever you use, the result is the same.
They are identical since both define a read-only computed property. But the former is preferable because it is shorter and more readable than the latter.

Swift extension for getting instance private property

I'm using this open source library which is a wrapper on AddressBook.framework. There's no method for deleting contact, so I'm gonna use default ABAddressBookRemoveRecord. However for that I need the ABAddressBookRef.
Since it's declared in APAddressBook.m file of that APAddressBook library as
#property (nonatomic, readonly) ABAddressBookRef addressBook; and I'm not able to get access to it, I wanted to write extension in Swift, containing method returning it.
So this is body of my extension:
extension APAddressBook {
private struct AssociatedKey {
static var addressBookRef = "addressBook"
}
var xo: ABAddressBook! {
get {
return objc_getAssociatedObject(self, &AssociatedKey.addressBookRef)
}
set(newValue) {
objc_setAssociatedObject(self, &AssociatedKey.addressBookRef, newValue, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN))
}
}
func getABAddressBook() -> ABAddressBookRef {
return self.xo
}
}
I've also tried using private var xoAssociationKey: UInt8 = 0 as associatedKey, but calling getABAddressBook() function always crashes with fatal error: unexpectedly found nil while unwrapping an Optional value.
What's wrong with my code? Also is there better way to solve my problem?
Well maybe it's not particulary an answer to your questions but here is some thoughts.
You only know what to pass in obc_objc_getAssociatedObject because your lib is open source.
So why wouldnt you use that to fit it under your needs?
If i were you I'd just move that property to the public access. I dont find it a really worse solution than trying to access private property via obc_ methods.
Regarding your question did you try to specify addressBookRef as : NSString? Since Apple now made swift's String and NSString two different types.

Using non NS_ENUM objective-C enum in swift

I am using the wahoo fitness API and it defines the following objective-C enum:
typedef enum
{
/** No active connection. */
WF_SENSOR_CONNECTION_STATUS_IDLE,
/** The connection is in process of being established. */
WF_SENSOR_CONNECTION_STATUS_CONNECTING,
/** The sensor connection is established and active. */
WF_SENSOR_CONNECTION_STATUS_CONNECTED,
/** The connection was interrupted (usually occurs when fisica is disconnected). */
WF_SENSOR_CONNECTION_STATUS_INTERRUPTED,
/** The connection is in process of being disconnected. */
WF_SENSOR_CONNECTION_STATUS_DISCONNECTING,
} WFSensorConnectionStatus_t;
I can't find a way to use it in swift. I first tried to do a switch/case on it without success. I am at a point I just want to carry on and tried the following:
var connState : WFSensorConnectionStatus_t = WF_SENSOR_CONNECTION_STATUS_IDLE
...
if( connState == WF_SENSOR_CONNECTION_STATUS_IDLE){
But it does not compile:
'WFSensorConnectionStatus_t' is not convertible to 'NSObject'
Any workaround? I read to use WFSensorConnectionStatus_t.WF_SENSOR_CONNECTION_STATUS_IDLE or WF_SENSOR_CONNECTION_STATUS_IDLE.value but it does not work in xcode beta-4.
The workaround to use .value to get the underlying integer doesn't work anymore as of Beta 4, as you said.
Unfortunately an enum is not transferrable to Swift from Objective-C, it needs to be an NS_ENUM.
I have the same setup as you in a project where I need the enum from an Objective-C framework and use it in Swift.
The workaround I did was to create an Objective-C category that contains an NS_ENUM and there I transfer the values from the framework enum to my own NS_ENUM.
Import the category in your bridging header and you should be able to use the enum as you normally would do.
Something like this:
typedef NS_ENUM(NSUInteger, ConnectionStatus) {
ConnectionStatusIdle
}
- (ConnectionStatus)connectionStatus {
if [self getConnectionStatus] == WF_SENSOR_CONNECTION_STATUS_IDLE {
return ConnectionStatusIdle
}
}
Then you should be able to use it like this:
switch myObject.connectionStatus() {
case .Idle:
// do something
break
}
Here is the final complete solution:
WFSensorConnection+SensorConnectionEnumCategory.h
:
#import <Foundation/Foundation.h>
#import <WFConnector/WFConnector.h>
#interface WFSensorConnection (SensorConnectionEnumCategory)
typedef NS_ENUM(NSUInteger, ConnectionStatus) {
ConnectionStatusIdle,
ConnectionStatusConnecting,
ConnectionStatusConnected,
ConnectionStatusInterrupted,
ConnectionStatusDisconnecting
};
- (ConnectionStatus) swift_connectionStatus;
#end
WFSensorConnection+SensorConnectionEnumCategory.m
:
#import "WFSensorConnection+SensorConnectionEnumCategory.h"
#implementation WFSensorConnection (SensorConnectionEnumCategory)
- (ConnectionStatus) swift_connectionStatus{
if ( [self connectionStatus] == WF_SENSOR_CONNECTION_STATUS_IDLE ){
return ConnectionStatusIdle;
} else if ( [self connectionStatus] == WF_SENSOR_CONNECTION_STATUS_CONNECTING ){
return ConnectionStatusConnecting;
} else if ( [self connectionStatus] == WF_SENSOR_CONNECTION_STATUS_CONNECTED ){
return ConnectionStatusConnected;
} else if ( [self connectionStatus] == WF_SENSOR_CONNECTION_STATUS_DISCONNECTING ){
return ConnectionStatusDisconnecting;
} else if ( [self connectionStatus] == WF_SENSOR_CONNECTION_STATUS_INTERRUPTED ){
return ConnectionStatusInterrupted;
}
return 0;
}
#end
Bridging-Header.h
:
#import "WFSensorConnection+SensorConnectionEnumCategory.h"
Usage:
var sensorConnection: WFSensorConnection?
var connState : ConnectionStatus = ConnectionStatus.Idle
connState = sensorConnection!.swift_connectionStatus()
switch connState {
case ConnectionStatus.Idle:
...
}
C-style enums import in Swift like UInt32. So you can do something like:
let state = unsafeBitCast(WF_SENSOR_CONNECTION_STATUS_IDLE, UInt32.self)
if state == unsafeBitCast(WF_SENSOR_CONNECTION_STATUS_IDLE, UInt32.self) {
//do something
}
Upd: In Swift 2.1 (Xcode 7.1 beta 2) all C-style enums conforms Equatable and you can now use it like:
let state = WF_SENSOR_CONNECTION_STATUS_IDLE
if state == WF_SENSOR_CONNECTION_STATUS_IDLE {
//do something
}
Profit :)
Note that there is a CoreFoundation type that is similar to NS_ENUM called CF_ENUM. I've used it on my framework that is mainly C. And yes, Swift does translate it to a Swift enum.
There is also something similar for NS_OPTIONS called CF_OPTIONS.

Using named value from enum in Objective C

I have an enum defined as follows:
typedef enum modifiers {
modifierNone=-1,
modifierCmd,
modifierShift,
modifierOption
} Modifier;
What i would like to do is pass a string value from one method to another for example (modifierCmd) and create the relevant Modifier to pass to a separate method.
- (void)methodOne:(NSString *)stringValue {
Modifier mod = (Modifier)stringValue;
[self methodTwo:mod];
}
Should this work?
Thanks
Nope. You can use a function, though:
Modifier makeModifier(NSString *s)
{
if ([s isEqualToString:#"modifierNone"]) {
return modifierNone;
} else if ([s isEqualToString:#"modifierCmd"]) {
return modifierCmd;
} /* etc... */
}
- (void)methodOne:(NSString *)stringValue
{
[self methodTwo:makeModifier(stringValue)];
}
I don't think it can work because the data type is really different. Enum is in fact, integer, when NSString is an object. You can use if else to check for modifier. But I recommend to pass the modifier directly.