How to typecast NSManagedObject class to Any to create a BehaviorRelay object in RxSwift? - rx-swift

I have an Entity called 'CartItem' (NSManagedObject class) in my coredata datamodelid. Wanted to change Variable to BehaviorRelay in RxSwift, but I get a compile time error stating "[Any] is not convertible to CartItem". How do I change Variable to BehaviorRelay?
var cartItemsArray = BehaviorRelay<CartItem>(value: []) //get error here
//var cartItemsArray: Variable<[CartItem]> = Variable([])

You forgot the brackets around CartItem.
let cartItemsArray = BehaviorRelay<[CartItem]>(value: [])
And don't make cartItemsArray a var, it should be a let.

Related

how do I do foo[bar] (partially dynamic property access) in fable?

I have a fairly simple javascript method
(props,propName,componentName) => {
var value = props[propName];
const getOrSpread = name =>
props[name] || props.spread && props.spread[name];
// remainder of function code omitted
}
that is working in javascript land. I'm trying to convert it to fable but either I can get it to have a definitely exists property access to .spread or dynamic access to props[propName] but not both
module JsxHelpers =
type IReactProps =
abstract member spread : obj
let isfuncOrNullPropType (props:IReactProps) (propName:string) componentName =
let propsO :obj = box props
let value:obj = propsO?propName
let valueAttempt2:obj = (box props)?(propName)
// rest of translation not attempted yet
value
where if props is defined as IReactProps, then .spread works, but neither of the two possible let value lines compile.
or props is defined as obj and it says `This expression was expected to have type 'obj' but here has type ''a -> obj'
even the simplest object from the documentation doesn't appear to compile:
let isfuncOrNullPropType (props:obj) (propName:string) =
let value2:obj = props?propName
value2
using "fable-core": "^1.0.0-narumi-905"
You definitely need to put the prop name in parentheses according to the documentation. The compiler error you're getting is because props?(propName) returns type 'a -> obj. Apparently, the dynamic (?) operator returns an Applicable, and from the fable source:
/// DO NOT USE: Internal type for Fable dynamic operations
type Applicable = obj->obj
Perhaps try:
let value : obj = unbox<obj> (props?(propName))

Iterating over a collection in Swift: var vs. let

I have a method that iterates over an array and call other method with every element as argument. If I declare this method as:
func didFinishedListFiles(files: [FileModel]) {
for var fileData in files {
self.downloadSingleFile(NSUUID(UUIDString: fileData.uuid!)!);
}
}
Xcode shows a warning:
Variable 'fileData' was never mutated; consider changing to 'let' constant
But if I change var to let:
func didFinishedListFiles(files: [FileModel]) {
for let fileData in files {
self.downloadSingleFile(NSUUID(UUIDString: fileData.uuid!)!);
}
}
Xcode shows an error:
'let' pattern cannot appear nested in an already immutable context
How is a correct way to implement it without any warnings/errors?
The for-in pattern implicitly uses a constant binding (in the scope it creates. That is, your fileData binding is automatically a local let, and therefore constant for each pass through the loop.
So the following:
for fileData in files { /*...*/ }
...is equivalent to :
var index = 0
while index < files.count {
let fileData = files[index]
//...
index += 1
}
You'd want to add var to the for-in binding only when you want to mutate that binding -- that is, if it's an object reference that you want to be able to point at something else during a single pass through the loop, or a value type that you want to be able to change. But it doesn't look like you're doing either of those things, so using var for this binding would be superfluous here.
(Swift 3 got rid of a lot of the places where you could make implicitly immutable bindings mutable, but left for var as an exception — it's still possible if you want to change something during a loop.)

Can I use Expression.Call on Generic and Static Methods?

I'm trying to use Expression.Call on a generic, static Method.
Unfortunately, there is no signature of the Call Method allowing to give generic type arguments AND a method info argument.
Is this possibly in any way?
What I'm concretely trying to do is to write a helper class that can sort an IEnumerable(DataRow) via Linq dynamically.
Unfortunately, I have to use the DataRowExtensions to get the Field I want to sort in the Lambda expression.
The original code comes from http://aonnull.blogspot.de/2010/08/dynamic-sql-like-linq-orderby-extension.html.
The (experimental) piece of code looks at the moment as follows:
//T is DataRow
Type type = typeof(T);
IEnumerable<MethodInfo> extensions = GetExtensionMethods(Assembly.GetAssembly(typeof(DataRowExtensions)), typeof(DataRow));
ParameterExpression arg = Expression.Parameter(typeof(DataRow), "x");
//at Position 0 there is T Field<T>(string)
MethodInfo mi = extensions.ToList()[0];
var methArg = Expression.Parameter(typeof(String), "\"" + orderByInfo + "\"");
MethodCallExpression expr = Expression.Call(null, mi, arg, methArg);
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), typeof(Object));
LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);
When Runtime comes to the Expression.Call Statement an Exception is thrown saying that the Field-Method is generic.
So, yes. When you get MethodInfo for Field method, you really get generic method, without specify what type for return value.
T Field<T>(string)
For solving, just use MakeGenericMethod from this method with needed type, like
MethodInfo mi = extensions.ToList()[0].MakeGenericMethod(typeof(object));
here mi already specify generic parameter and present function
object Field(string);
Also you a bit complicate your code, so you can a bit simplified it and get something like this
//T is DataRow
Type type = typeof(T);
IEnumerable<MethodInfo> extensions = GetExtensionMethods(Assembly.GetAssembly(typeof(DataRowExtensions)), type);//if T is DataRow not needed get typeof again
ParameterExpression arg = Expression.Parameter(typeof(DataRow), "x");
//at Position 0 there is T Field<T>(string)
MethodInfo mi = extensions.ToList()[0].MakeGenericMethod(typeof(object));//you can change object type to needed type
var methArg = Expression.Parameter(typeof(String), orderByInfo);//if orderByInfo already string, then not needed wrap it in quotes
LambdaExpression lambda = Expression.Lambda<Func<T,string,object>>(
Expression.Call(mi, arg, methArg), //call mi with args: arg, methArg
arg,methArg);//pass parameters
Sidenote: you can not specify name for parameter, in this case name would be generate automatically, like: Param_0,Param_1 and etc.
You anyway not use parameter name directly.

Swift double unwrapping of Optionals

I understand what optional are in Swift but I just encountered a ”Double Wrapped Optional’, where if I don’t use two '!' Xcode gives an complier error
Value of optional type 'String?' not unwrapped; did you mean to use '!' or ‘?'?
I have the following code, where app is of type NSRunningApplication.
let name: String = app.localizedName!
Why should I have to use two !? Isn’t one enough to unwrap the variable because it is of type var localizedName: String?.
Context:
Xcode want me to use let name: String = app.localizedName!!, otherwise it gives the compiler error above.
The app variable is defined as follow:
var apps = NSWorkspace().runningApplications.filter{$0.activationPolicy == NSApplicationActivationPolicy.Regular}
for app in apps{
//code posted above
…
}
So I know that app is not an optional and will always have a value, nor is it an optional application.
P.S. Is there a way to define type when using fast enumeration? Like for Foo(app) in apps where apps = [AnyObject].
The problem is that NSWorkspace().runningApplications returns an
array of AnyObject which has to be cast to an array of
NSRunningApplication:
let apps = NSWorkspace().runningApplications as! [NSRunningApplication]
let filteredApps = apps.filter {
$0.activationPolicy == NSApplicationActivationPolicy.Regular
}
for app in apps {
let name: String = app.localizedName!
}
Here's why: app is of type AnyObject (id in Objective-C), and doing any lookup on AnyObject introduces a layer of optionality because of the possibility that the method doesn’t exist on the object. localizedName is itself Optional, so you end up with two levels of optional: the outer level is nil if the object doesn’t respond to localizedName, and the inner is nil if 'localizedName' is nil.

Is Swift type-inference contradicting itself here?

Here's my test code:
var myDict: [String: AnyObject] = ["k":"v"]
var a = myDict["k"]
var b = a as String
var c = myDict["k"] as String
Here's my Swift playground in Xcode6-beta6:
According to the rules of type inference, doesn't complaining about c logically contradict not-complaining about b?
I believe that this is a bug. Part of what is going on here is that String is not an object. If you change the first line to:
var myDict: [String: Any] = ["k":"v"]
then everything is fine. So, given that string is not an object, casting a variable of type AnyObject? to a String should definitely yield an error. And, since the compiler has already decided that a is of type AnyObject? it should complain about casting a to a String.
Note that if you change the last line to:
var c = myDict["k"] as NSString
the error goes away supporting the notion that the issue is that String is not an object. You get the same complaint if you put an Int as the value in the array and try to cast that to an Int.
Update:
So the plot thickens. If you don't import Foundation or import something that imports Foundation, then you get additional errors. Without Foundation:
So clearly some of this has to do with the dual nature of Strings as non-objects and NSStrings as objects and the ability to use Strings as NSStrings when Foundation is imported.
This has to do with the fact that Dictionary has two subscript overloads:
subscript (key: Key) -> Value?
subscript (i: DictionaryIndex<Key, Value>) -> (Key, Value) { get }
The first is the familiar one where you pass a key and it gives you an optional of the value; and you can use to set the value on a key.
The second one is less common. I believe DictionaryIndex is a kind of iterator into the dictionary, and you can use it as a subscript to directly get the key-value pair at that iterator.
When the compiler can't find an overload that matches (in this case, the first one doesn't match because it returns an optional, which cannot be cast to non-optional String), it just picks one arbitrarily (well, it seems arbitrary to me anyway) to show in the error. In this place, it picks the second one, which you don't recognize. That's why the error seems weird to you.
This works.
var c = myDict["k"] as AnyObject! as String // "v"
To answer your question, the reason Swift complains could be that you are trying to do these two conversions in one go. Remember, the statement var a = myDict["k"] contains an implicit conversion already. The implied conversion is AnyObject?, so the above would also work like this:
var c = myDict["k"] as AnyObject? as String // "v"
Note that the above would lead to a run time error if the key "k" where not defined. You would allow this to return nil by casting to String?.

Resources