Does _Arraytype or _Arrayprotocol Not Available in Swift 3.1

Does _ArrayType or _ArrayProtocol not available in Swift 3.1?

Type names starting with an underscore should always treated as internal.
In Swift 3.1, it is marked as internal in the source code and therefore
not publicly visible.

Using _ArrayProtocol was a workaround in earlier Swift versions where
you could not define an Array extension with a "same type" requirement.
This is now possible as of Swift 3.1, as described in the
Xcode 8.3 release notes:

Constrained extensions allow same-type constraints between generic parameters and concrete types. (SR-1009)

Using the internal protocol is therefore not necessary anymore,
and you can simply define

extension Array where Element == UInt8 {

}

But note that your static func stringValue() does not need any
restriction of the element type. What you perhaps intended is to
define an instance method like this:

extension Array where Element == UInt8 {

func stringValue() -> String {
return String(cString: self)
}

}

print([65, 66, 67, 0].stringValue()) // ABC

Also note that String(cString:) expects a null-terminated sequence
of UTF-8 bytes.

How can I make a extension for array of specific type in Swift

for say the specific type is S

extension CollectionType where Generator.Element == S {
}

CollectionType Protocol

Usage of protocols as array types and function parameters in swift

As of Swift 5.7 / Xcode 14 this can now elegantly be solved using any.

protocol SomeProtocol: Equatable {
func bla()
}

class SomeClass {
var protocols = [any SomeProtocol]()

func addElement(element: any SomeProtocol) {
protocols.append(element)
}

func removeElement(element: any SomeProtocol) {
if let index = find(protocols, element) {
protocols.remove(at: index)
}
}
}

Array of protocol type

What you need to do is to use type erasure, much like AnyHashable does in the Swift Standard Library.

You can't do:

var a: [Hashable] = [5, "Yo"]
// error: protocol 'Hashable' can only be used as a generic constraint because it has Self or associated type requirements

What you have to do is to use the type-erased type AnyHashable:

var a: [AnyHashable] = [AnyHashable(5), AnyHashable("Yo")]
a[0].hashValue // => shows 5 in a playground

So your solution would be to first split the protocol in smaller parts and promote Equatable to Hashable (to reuse AnyHashable)

protocol Conditionable {
var condition: Condition? { get set }
}

protocol Executable {
func execute() -> SKAction
}

protocol Commandable: Hashable, Executable, Conditionable {}

Then create an AnyCommandable struct, like this:

struct AnyCommandable: Commandable, Equatable {
var exeBase: Executable
var condBase: Conditionable
var eqBase: AnyHashable

init<T: Commandable>(_ commandable: T) where T : Equatable {
self.condBase = commandable
self.exeBase = commandable
self.eqBase = AnyHashable(commandable)
}

var condition: Condition? {
get {
return condBase.condition
}
set {
condBase.condition = condition
}
}

var hashValue: Int {
return eqBase.hashValue
}

func execute() -> SKAction {
return exeBase.execute()
}

public static func ==(lhs: AnyCommandable, rhs: AnyCommandable) -> Bool {
return lhs.eqBase == rhs.eqBase
}
}

And then you can use it like this:

var a = FunctionCommand()
a.commands = [AnyCommandable(MoveCommand()), AnyCommandable(FunctionCommand())]

And you can easily access properties of commands, because AnyCommandable implements Commandable

a.commands[0].condition

You need to remember to now add Hashable and Equatable to all your commands.
I used those implementations for testing:

struct MoveCommand: Commandable {

var movingVector: CGVector!

var condition: Condition?
func execute() -> SKAction {
return SKAction()
}

var hashValue: Int {
return Int(movingVector.dx) * Int(movingVector.dy)
}

public static func ==(lhs: MoveCommand, rhs: MoveCommand) -> Bool {
return lhs.movingVector == rhs.movingVector
}
}

struct FunctionCommand: Commandable {
var commands = [AnyCommandable]()

var condition: Condition?

func execute() -> SKAction {
return SKAction.group(commands.map { $0.execute() })
}

var hashValue: Int {
return commands.count
}

public static func ==(lhs: FunctionCommand, rhs: FunctionCommand) -> Bool {
return lhs.commands == rhs.commands
}
}

Difference between various type of Variable declaration in swift

Array is a swift type where as NSArray is an objective C type. NS classes support dynamic-dispatch and technically are slightly slower to access than pure swift classes.

1) var arr = NSArray()

arr is an NSArray() here - you can re-assign things to arr but you can't change the contents of the NSArray() - this is a bad choice to use IMO because you've put an unusable array into the variable. I really can't think of a reason you would want to make this call.

2) var arr = NSMutableArray()

Here you have something usable. because the array is mutable you can add and remove items from it

3) var arr = Array()

This won't compile - but var arr = Array<Int>() will.

Array takes a generic element type ( as seen below)

public struct Array<Element> : CollectionType, MutableCollectionType, _DestructorSafeContainer {
/// Always zero, which is the index of the first element when non-empty.
public var startIndex: Int { get }
/// A "past-the-end" element index; the successor of the last valid
/// subscript argument.
public var endIndex: Int { get }
public subscript (index: Int) -> Element
public subscript (subRange: Range<Int>) -> ArraySlice<Element>
}

4) var arr : NSMutableArray?

You are defining an optional array here. This means that arr starts out with a value of nil and you an assign an array to it if you want later - or just keep it as nil. The advantage here is that in your class/struct you won't actually have to set a value for arr in your initializer

5) var arr : NSMutableArray = []

Sample Image

It sounds like you are hung up on confusion about Optional values.

Optional means it could be nil or it could not

When you type something as type? that means it is nil unless you assign it something, and as such you have to unwrap it to access the values and work with it.

Can I use a protocol array in ForEach?

Ok, let's make it work.

The issue

In your case, the compiler expects parameter \.self to be Hashable and this parameter is an object of your protocol GalleryItem.

The solution

To solve this, we can add a requirement to the protocol that can provide an \.id. For example:

protocol GalleryItem {
func toView() -> AnyView
var id: Int { get } // could be any `Hashable` type
}

And then, instead of using \.self in the ForEach as identifier, we can use \.id as an identifier:

ForEach(items, id: \.id) { item in
item.toView()
}

The naming and the type here are pretty much up to you. \.id and Int are used as an example.



Related Topics



Leave a reply



Submit