I have the following code:
class Function<T> {
var ptr: () throws -> T
init<Func>(block: Func, args: AnyObject...) {
self.ptr = {() throws -> T in
let result: AnyObject? = nil
if T.self == Void.self {
return Void() as! T
}
return result //Error Here.. Cannot as! cast it either.. Cannot unsafeBitCast it either..
}
}
}
postfix operator ^ { }
postfix func ^ <T>(left: Function<T>) throws -> T {
return try left.ptr()
}
func call() {
let block: (String) -> String? = {(arg) -> String? in
return nil
}
let fun = Function<String?>(block: block, args: "Hello")
fun^
}
The function Block.execute returns AnyObject?. My Generic class Function<T> expects a return type of T.
If T is already String? why can't I return nil?
Is there any way to return nil as type T which is already Optional?
If I make T Optional, then the return type becomes Optional<Optional<String>> which is not what I want.. then the compiler complains that OptionalOptional is not unwrapped with ?? That is how I know that T is already optional.
After a long hunt on google I have finally found an elegant way to do this. It's possible to write a class extension with type constraints.
class Foo<T> {
func bar() -> T {
return something
// Even if T was optional, swift does not allow us to return nil here:
// 'nil' is incompatible with return type 'T'
}
}
extension Foo where T: ExpressibleByNilLiteral {
func bar() -> T {
return nil
// returning nil is now allowed
}
}
The appropriate method will be invoked depending on whether T is optional or not.
I solved it with a nasty work around.. I throw an exception for nil return type. Then in the generic function operator I catch that specific exception and return nil if T is NilLiteralConvertible.. Otherwise I just execute normally..
class Function<T> {
var ptr: () throws -> T
init<Func>(block: Func, args: AnyObject...) {
self.ptr = {() throws -> T in
let result: AnyObject? = execute(block, args...)
if T.self == Void.self {
return Void() as! T
}
throw BlockError.BlockReturnsNil
}
}
}
postfix func ^ <T>(left: Function<T>) throws -> T {
return try left.ptr()
}
postfix func ^ <T : NilLiteralConvertible>(left: Function<T>) throws -> T {
do {
return try left.ptr()
}
catch BlockError.BlockReturnsNil {
return nil
}
}
The following casts Any? to T returning nil only if T is optional and from is nil. It crashes, if from cannot be cast to T.
func cast<T>(from v: Any?)->T {
return v as! T
}
func cast<T>(from v: Any?)->T where T: ExpressibleByNilLiteral {
guard let v = v else { return nil }
return v as! T
}
This does the trick as of Swift 3.1. Modification of user3763801's answer.
func cast<T>(_ v: Any) -> T {
return v as! T
}
What I want to implement:
class func getSomeObject() -> [SomeObject]? {
let objects = Realm().objects(SomeObject)
return objects.count > 0 ? objects : nil
}
How can I return object as [SomeObject] instead if Results?
Weird, the answer is very straightforward. Here is how I do it:
let array = Array(results) // la fin
If you absolutely must convert your Results to Array, keep in mind there's a performance and memory overhead, since Results is lazy. But you can do it in one line, as results.map { $0 } in swift 2.0 (or map(results) { $0 } in 1.2).
I found a solution. Created extension on Results.
extension Results {
func toArray<T>(ofType: T.Type) -> [T] {
var array = [T]()
for i in 0 ..< count {
if let result = self[i] as? T {
array.append(result)
}
}
return array
}
}
and using like
class func getSomeObject() -> [SomeObject]? {
let objects = Realm().objects(SomeObject).toArray(SomeObject) as [SomeObject]
return objects.count > 0 ? objects : nil
}
With Swift 4.2 it's as simple as an extension:
extension Results {
func toArray() -> [Element] {
return compactMap {
$0
}
}
}
All the needed generics information is already a part of Results which we extend.
To use this:
let someModelResults: Results<SomeModel> = realm.objects(SomeModel.self)
let someModelArray: [SomeModel] = someModelResults.toArray()
This an another way of converting Results into Array with an extension with Swift 3 in a single line.
extension Results {
func toArray() -> [T] {
return self.map { $0 }
}
}
For Swift 4 and Xcode 9.2
extension Results {
func toArray<T>(type: T.Type) -> [T] {
return flatMap { $0 as? T }
}
}
With Xcode 10 flatMap is deprecated you can use compactMap for mapping.
extension Results {
func toArray<T>(type: T.Type) -> [T] {
return compactMap { $0 as? T }
}
}
Swift 3
extension Results {
func toArray<T>(ofType: T.Type) -> [T] {
var array = [T]()
for i in 0 ..< count {
if let result = self[i] as? T {
array.append(result)
}
}
return array
}
}
Usage
class func getSomeObject() -> [SomeObject]? {
let defaultRealm = try! Realm()
let objects = defaultRealm.objects(SomeObject.self).toArray(ofType : SomeObject.self) as [SomeObject]
return objects.count > 0 ? objects : nil
}
Alternative : Using generics
class func getSomeObject() -> [T]? {
let objects = Realm().objects(T.self as! Object.Type).toArray(ofType : T.self) as [T]
return objects.count > 0 ? objects : nil
}
it's not a good idea to convert Results to Array, because Results is lazy. But if you need try this:
func toArray<T>(ofType: T.Type) -> [T] {
return flatMap { $0 as? T }
}
but better way is to pass Results wherever you need. Also you can convert Results to List instead of Array.
List(realm.objects(class))
if the first func is not working you can try this one:
var refrenceBook:[RefrenceProtocol] = []
let faceTypes = Array(realm.objects(FaceType))
refrenceBook = faceTypes.map({$0 as FaceType})
Solution for Swift 4, Realm 3
extension Results {
func toArray<T>(ofType: T.Type) -> [T] {
let array = Array(self) as! [T]
return array
}
}
Now converting can be done as below
let array = Realm().objects(SomeClass).toArray(ofType: SomeClass.self)
I'm not sure, if there is any efficient way to do this.
But you can do it by create a Swift array and append it in the loop.
class func getSomeObject() -> [SomeObject]? {
var someObjects: [SomeObject] = []
let objects = Realm().objects(SomeObject)
for object in objects{
someObjects += [object]
}
return objects.count > 0 ? someObjects : nil
}
If you feel it's too slow. I recommend you to pass around Realm Results object directly.
extension Results {
var array: [Element]? {
return self.count > 0 ? self.map { $0 } : nil
}
}
So, you can use like:
Realm().objects(SomeClass.self).filter("someKey ENDSWITH %#", "sth").array
extension Results {
func materialize() -> [Element] {
return Array(self)
}
}
Using Swift 5 and RealmSwift v10.20.0
This methods works:
private func convertToArray<R>(results: Results<R>) -> [R] where R: Object {
var arrayOfResults: [R] = []
for result in results {
arrayOfResults.append(result)
}
return arrayOfResults
}
I have a container class that has an underlying dictionary. I have implemented subscripts for this class to access member of the underlying dictionary. Now, I am trying to create a sequence on this class so that I could iterate over all the elements of the underlying dictionary by using 'for-in' loop on the class instance itself. I have been looking to find some examples for Sequences for Swift Dictionary but could not find anything that explains the stuff well. I have seen some custom sequence examples for Swift Array but none for the Swift Dictionary. I would really appreciate if anyone could explain how I can achieve that. Following is the code for the class (no sequence code yet as I am not sure where to begin)
import Foundation
class STCQuestionList : GeneratorType, SequenceType {
private var questionDict: [String : STCQuestion] = [ : ];
subscript(key : String?) -> STCQuestion? {
get {
if (key != nil) {
return self.questionDict[key!];
}
return nil;
}
set(newValue) {
if (key != nil) {
self.questionDict[key!] = newValue;
}
}
}
func generate() -> GeneratorType {
}
func next() -> (String, STCQuestion)? {
if (self.questionDict.isEmpty) {
return .None
}
}
}
If I'm understanding correctly, how about just forwarding on the generate?
func generate() -> DictionaryGenerator<String, STCQuestion> {
return questionDict.generate()
}
(You don't need to implement GeneratorType, just SequenceType should do. It's generate() itself that returns a GeneratorType, and that's what has to implement next(), which the existing generate() implementation in Dictionary already does for you.)
Full worked example based on your code:
// Playground - noun: a place where people can play
import Foundation
class STCQuestion {
let foo: String
init(_ foo: String) {
self.foo = foo
}
}
class STCQuestionList : SequenceType {
private var questionDict: [String : STCQuestion] = [ : ];
subscript(key : String?) -> STCQuestion? {
get {
if key != nil {
return self.questionDict[key!];
}
return nil;
}
set(newValue) {
if key != nil {
self.questionDict[key!] = newValue;
}
}
}
func generate() -> DictionaryGenerator<String, STCQuestion> {
return questionDict.generate()
}
}
var list = STCQuestionList()
list["test"] = STCQuestion("blah")
list["another"] = STCQuestion("wibble")
list["third"] = STCQuestion("doodah")
for (key, value) in list {
println("Key: \(key) Foo: \(value.foo)")
}
// Output:
// Key: test Foo: blah
// Key: another Foo: wibble
// Key: third Foo: doodah
(Note: I re-thought this -- original answer via the edited page...)
Swift has a generic GeneratorOf type that you can use to create a generator. You just provide a closure that returns the next value in the initializer:
class STCQuestionList : SequenceType {
private var questionDict: [String : STCQuestion] = [ : ];
subscript(key : String?) -> STCQuestion? {
get {
if (key != nil) {
return self.questionDict[key!];
}
return nil;
}
set(newValue) {
if (key != nil) {
self.questionDict[key!] = newValue;
}
}
}
/// Creates a generator for each (key, value)
func generate() -> GeneratorOf<(String, STCQuestion)> {
var index = 0
return GeneratorOf<(String, STCQuestion)> {
if index < self.questionDict.keys.array.count {
let key = self.questionDict.keys.array[index++]
return (key, self.questionDict[key]!)
} else {
return nil
}
}
}
}
If you don't care about the order, can't you just call the same methods of dictionary or make your class a subclass of a dictionary? For example:
func generate() -> GeneratorType {
return self.questionDict.generate()
}
func next() -> (String, STCQuestion)? {
return self.questionDict.next()
}
extension Array {
func removeObject<T where T : Equatable>(object: T) {
var index = find(self, object)
self.removeAtIndex(index)
}
}
However, I get an error on var index = find(self, object)
'T' is not convertible to 'T'
I also tried with this method signature: func removeObject(object: AnyObject), however, I get the same error:
'AnyObject' is not convertible to 'T'
What is the proper way to do this?
As of Swift 2, this can be achieved with a protocol extension method.
removeObject() is defined as a method on all types conforming
to RangeReplaceableCollectionType (in particular on Array) if
the elements of the collection are Equatable:
extension RangeReplaceableCollectionType where Generator.Element : Equatable {
// Remove first collection element that is equal to the given `object`:
mutating func removeObject(object : Generator.Element) {
if let index = self.indexOf(object) {
self.removeAtIndex(index)
}
}
}
Example:
var ar = [1, 2, 3, 2]
ar.removeObject(2)
print(ar) // [1, 3, 2]
Update for Swift 2 / Xcode 7 beta 2: As Airspeed Velocity noticed
in the comments, it is now actually possible to write a method on a generic type that is more restrictive on the template, so the method
could now actually be defined as an extension of Array:
extension Array where Element : Equatable {
// ... same method as above ...
}
The protocol extension still has the advantage of being applicable to
a larger set of types.
Update for Swift 3:
extension Array where Element: Equatable {
// Remove first collection element that is equal to the given `object`:
mutating func remove(object: Element) {
if let index = index(of: object) {
remove(at: index)
}
}
}
Update for Swift 5:
extension Array where Element: Equatable {
/// Remove first collection element that is equal to the given `object` or `element`:
mutating func remove(element: Element) {
if let index = firstIndex(of: element) {
remove(at: index)
}
}
}
You cannot write a method on a generic type that is more restrictive on the template.
NOTE: as of Swift 2.0, you can now write methods that are more restrictive on the template. If you have upgraded your code to 2.0, see other answers further down for new options to implement this using extensions.
The reason you get the error 'T' is not convertible to 'T' is that you are actually defining a new T in your method that is not related at all to the original T. If you wanted to use T in your method, you can do so without specifying it on your method.
The reason that you get the second error 'AnyObject' is not convertible to 'T' is that all possible values for T are not all classes. For an instance to be converted to AnyObject, it must be a class (it cannot be a struct, enum, etc.).
Your best bet is to make it a function that accepts the array as an argument:
func removeObject<T : Equatable>(object: T, inout fromArray array: [T]) {
}
Or instead of modifying the original array, you can make your method more thread safe and reusable by returning a copy:
func arrayRemovingObject<T : Equatable>(object: T, fromArray array: [T]) -> [T] {
}
As an alternative that I don't recommend, you can have your method fail silently if the type stored in the array cannot be converted to the the methods template (that is equatable). (For clarity, I am using U instead of T for the method's template):
extension Array {
mutating func removeObject<U: Equatable>(object: U) {
var index: Int?
for (idx, objectToCompare) in enumerate(self) {
if let to = objectToCompare as? U {
if object == to {
index = idx
}
}
}
if(index != nil) {
self.removeAtIndex(index!)
}
}
}
var list = [1,2,3]
list.removeObject(2) // Successfully removes 2 because types matched
list.removeObject("3") // fails silently to remove anything because the types don't match
list // [1, 3]
Edit To overcome the silent failure you can return the success as a bool:
extension Array {
mutating func removeObject<U: Equatable>(object: U) -> Bool {
for (idx, objectToCompare) in self.enumerate() { //in old swift use enumerate(self)
if let to = objectToCompare as? U {
if object == to {
self.removeAtIndex(idx)
return true
}
}
}
return false
}
}
var list = [1,2,3,2]
list.removeObject(2)
list
list.removeObject(2)
list
briefly and concisely:
func removeObject<T : Equatable>(object: T, inout fromArray array: [T])
{
var index = find(array, object)
array.removeAtIndex(index!)
}
After reading all the above, to my mind the best answer is:
func arrayRemovingObject<U: Equatable>(object: U, # fromArray:[U]) -> [U] {
return fromArray.filter { return $0 != object }
}
Sample:
var myArray = ["Dog", "Cat", "Ant", "Fish", "Cat"]
myArray = arrayRemovingObject("Cat", fromArray:myArray )
Swift 2 (xcode 7b4) array extension:
extension Array where Element: Equatable {
func arrayRemovingObject(object: Element) -> [Element] {
return filter { $0 != object }
}
}
Sample:
var myArray = ["Dog", "Cat", "Ant", "Fish", "Cat"]
myArray = myArray.arrayRemovingObject("Cat" )
Swift 3.1 update
Came back to this now that Swift 3.1 is out. Below is an extension which provides exhaustive, fast, mutating and creating variants.
extension Array where Element:Equatable {
public mutating func remove(_ item:Element ) {
var index = 0
while index < self.count {
if self[index] == item {
self.remove(at: index)
} else {
index += 1
}
}
}
public func array( removing item:Element ) -> [Element] {
var result = self
result.remove( item )
return result
}
}
Samples:
// Mutation...
var array1 = ["Cat", "Dog", "Turtle", "Cat", "Fish", "Cat"]
array1.remove("Cat")
print(array1) // ["Dog", "Turtle", "Socks"]
// Creation...
let array2 = ["Cat", "Dog", "Turtle", "Cat", "Fish", "Cat"]
let array3 = array2.array(removing:"Cat")
print(array3) // ["Dog", "Turtle", "Fish"]
With protocol extensions you can do this,
extension Array where Element: Equatable {
mutating func remove(object: Element) {
if let index = indexOf({ $0 == object }) {
removeAtIndex(index)
}
}
}
Same functionality for classes,
Swift 2
extension Array where Element: AnyObject {
mutating func remove(object: Element) {
if let index = indexOf({ $0 === object }) {
removeAtIndex(index)
}
}
}
Swift 3
extension Array where Element: AnyObject {
mutating func remove(object: Element) {
if let index = index(where: { $0 === object }) {
remove(at: index)
}
}
}
But if a class implements Equatable it becomes ambiguous and the compiler gives an throws an error.
With using protocol extensions in swift 2.0
extension _ArrayType where Generator.Element : Equatable{
mutating func removeObject(object : Self.Generator.Element) {
while let index = self.indexOf(object){
self.removeAtIndex(index)
}
}
}
what about to use filtering? the following works quite well even with [AnyObject].
import Foundation
extension Array {
mutating func removeObject<T where T : Equatable>(obj: T) {
self = self.filter({$0 as? T != obj})
}
}
Maybe I didn't understand the question.
Why wouldn't this work?
import Foundation
extension Array where Element: Equatable {
mutating func removeObject(object: Element) {
if let index = self.firstIndex(of: object) {
self.remove(at: index)
}
}
}
var testArray = [1,2,3,4,5,6,7,8,9,0]
testArray.removeObject(object: 6)
let newArray = testArray
var testArray2 = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
testArray2.removeObject(object: "6")
let newArray2 = testArray2
No need to extend:
var ra = [7, 2, 5, 5, 4, 5, 3, 4, 2]
print(ra) // [7, 2, 5, 5, 4, 5, 3, 4, 2]
ra.removeAll(where: { $0 == 5 })
print(ra) // [7, 2, 4, 3, 4, 2]
if let i = ra.firstIndex(of: 4) {
ra.remove(at: i)
}
print(ra) // [7, 2, 3, 4, 2]
if let j = ra.lastIndex(of: 2) {
ra.remove(at: j)
}
print(ra) // [7, 2, 3, 4]
There is another possibility of removing an item from an array without having possible unsafe usage, as the generic type of the object to remove cannot be the same as the type of the array. Using optionals is also not the perfect way to go as they are very slow. You could therefore use a closure like it is already used when sorting an array for example.
//removes the first item that is equal to the specified element
mutating func removeFirst(element: Element, equality: (Element, Element) -> Bool) -> Bool {
for (index, item) in enumerate(self) {
if equality(item, element) {
self.removeAtIndex(index)
return true
}
}
return false
}
When you extend the Array class with this function you can remove elements by doing the following:
var array = ["Apple", "Banana", "Strawberry"]
array.removeFirst("Banana") { $0 == $1 } //Banana is now removed
However you could even remove an element only if it has the same memory address (only for classes conforming to AnyObject protocol, of course):
let date1 = NSDate()
let date2 = NSDate()
var array = [date1, date2]
array.removeFirst(NSDate()) { $0 === $1 } //won't do anything
array.removeFirst(date1) { $0 === $1 } //array now contains only 'date2'
The good thing is, that you can specify the parameter to compare. For example when you have an array of arrays, you can specify the equality closure as { $0.count == $1.count } and the first array having the same size as the one to remove is removed from the array.
You could even shorten the function call by having the function as mutating func removeFirst(equality: (Element) -> Bool) -> Bool, then replace the if-evaluation with equality(item) and call the function by array.removeFirst({ $0 == "Banana" }) for example.
Using indexOf instead of a for or enumerate:
extension Array where Element: Equatable {
mutating func removeElement(element: Element) -> Element? {
if let index = indexOf(element) {
return removeAtIndex(index)
}
return nil
}
mutating func removeAllOccurrencesOfElement(element: Element) -> Int {
var occurrences = 0
while true {
if let index = indexOf(element) {
removeAtIndex(index)
occurrences++
} else {
return occurrences
}
}
}
}
I finally ended up with following code.
extension Array where Element: Equatable {
mutating func remove<Element: Equatable>(item: Element) -> Array {
self = self.filter { $0 as? Element != item }
return self
}
}
Your problem is T is not related to the type of your array in anyway for example you could have
var array = [1,2,3,4,5,6]
array.removeObject(object:"four")
"six" is Equatable, but its not a type that can be compared to Integer, if you change it to
var array = [1,2,3,4,5,6]
extension Array where Element : Equatable {
mutating func removeObject(object: Element) {
filter { $0 != object }
}
}
array.removeObject(object:"four")
it now produces an error on calling removeObject for the obvious reason its not an array of strings, to remove 4 you can just
array.removeObject(object:4)
Other problem you have is its a self modifying struct so the method has to be labeled as so and your reference to it at the top has to be a var
Implementation in Swift 2:
extension Array {
mutating func removeObject<T: Equatable>(object: T) -> Bool {
var index: Int?
for (idx, objectToCompare) in self.enumerate() {
if let toCompare = objectToCompare as? T {
if toCompare == object {
index = idx
break
}
}
}
if(index != nil) {
self.removeAtIndex(index!)
return true
} else {
return false
}
}
}
I was able to get it working with:
extension Array {
mutating func removeObject<T: Equatable>(object: T) {
var index: Int?
for (idx, objectToCompare) in enumerate(self) {
let to = objectToCompare as T
if object == to {
index = idx
}
}
if(index) {
self.removeAtIndex(index!)
}
}
}
I am trying to extend Swift's Array class with the following func:
func containsObjectIdenticalTo(obj: T) -> Bool {
// objectPassingTest returns the first object passing the test
return objectPassingTest { x in x == obj }
}
Apparently, this won't compile as the compiler doesn't know yet if == is implemented for type T. I then change the code to this
func containsObjectIdenticalTo(obj: T) -> Bool {
return objectPassingTest {
x in
assert(x is Equatable && obj is Equatable)
return (x as Equatable) == (obj as Equatable)
} != nil
}
Which doesn't work either, since conformance against Equatable can't be checked (because Equatable wasn't defined with #obj) !
Any thoughts on this? Would be nice if there's some way to assert directly if T conforms to Equatable, but I haven't read that anywhere. Swift seems to be less dynamic than Obj-C in these stuffs.
UPDATE:
Tried this suggestion and it doesn't work (don't know exactly what <T: Equatable> is for, tho it does compile).
func containsObjectIdenticalTo<T: Equatable>(obj: T) -> Bool {
var x = self[0]
var y = self[0]
return x == y // Error here
}
Specify that T must be equatable in the Method's signature:
func containsObjectIdenticalTo<T: Equatable>(obj: T) -> Bool {/*...*/}
i got this from ExSwift : https://github.com/pNre/ExSwift
func contains <T: Equatable> (items: T...) -> Bool {
return items.all { self.indexOf($0) >= 0 }
}
func indexOf <U: Equatable> (item: U) -> Int? {
if item is Element {
if let found = find(reinterpretCast(self) as Array<U>, item) {
return found
}
return nil
}
return nil
}
func all (call: (Element) -> Bool) -> Bool {
for item in self {
if !call(item) {
return false
}
}
return true
}
maybe you can try it
How about:
func containsObjectIdenticalTo<T : Equatable>(obj: T) -> Bool {
... etc ...
}
In the end, I resorted to this solution
func containsObjectIdenticalTo<U: Equatable>(obj: U) -> Bool {
return objectPassingTest({
x in
return x as U == obj
}) != nil
}
Might not be the best (ie safest) one. But it works great.