Subclass NSMutabaleArray in Swift

I am trying to subclass NSMutableArray in Swift, which supports an array literal initializer.

I can create a simple subclass:

 class MyArray: NSMutableArray { } 

And initialization works fine:

 let arrayInstance: MyArray = MyArray() 

However, if I try to use an array literal:

 let arrayInstance: MyArray = ["one"] 

It does not work at runtime, [NSMutableArray initWithCapacity:]: method only defined for abstract class. .

I can add this initializer, but as a result, I also need to add other necessary initializers:

 class MyArray: NSMutableArray { override init(capacity numItems: Int) { super.init(capacity: numItems) } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } required convenience init(arrayLiteral elements: AnyObject...) { fatalError("init(arrayLiteral:) has not been implemented") } } 

Unfortunately, the second required initializer gives the following compiler error:

Ads from extensions cannot be overridden

Looks like I'm stuck! Can anyone suggest a way to create a subclass of NSMutableArray that supports array literals? Otherwise, it will return to Objective-C for me!

+6
source share
1 answer

The problem here is not in array literals, also the first initialization does not work fine, you may get the β€œsame” failure if you do this:

 let arrayInstance: MyArray = MyArray() arrayInstance.count //OR let secondArrayInstance: MyArray = MyArray(objects: ["one"], count: 1) // method used by literals syntax 

The problem is subclassing NSMutableArray because it is a cluster of classes. According to Apple, there is no reason for this:

Normally there is no reason for a subclass of NSArray. A class does well that it is designed to maintain an ordered collection of objects. But there are times when a custom NSArray can come in handy. Here are a few possibilities:

Change how NSArray stores items in its collection. You could do this for performance reasons or for better compatibility with legacy code.

Obtaining additional information about what is happening with the collection (for example, collecting statistics).

Cluster Cluster Definition

Class Clusters is a design pattern that Foundation supports is widely used. Cluster groups group a number of private concrete subclasses under a public abstract superclass. Grouping classes in this way simplifies the publicly visible architecture of an object-oriented structure without reducing its functional richness. Class clusters are based on the Abstract Factory design pattern.

Alternatives to NSArray Subclassification

Before creating your own NSArray class, examine the NSPointerArray and its corresponding Core Foundation type, CFArray Reference. Because NSArray and CFArray are "duty free bridges", you can replace the CFArray for the NSArray in your code (with the appropriate Casting). Although they are appropriate types, CFArray and NSArray do not have the same interfaces or implementations, and you can sometimes do something with CFArray, which NSArray cannot handle easily. For example, CFArray provides a set of callbacks, some of which are designed to implement custom save-release behavior. if you specify NULL implementations for these callbacks, you can easily get an unsupported array.

If the behavior you want to add complements an existing class, you can write a category in NSArray. However, keep in mind that this category will apply to all instances of NSArray that you are using, and this may have unintended consequences. Alternatively, you can use the composition to achieve your desired behavior.

Subclass NSArray

In the NSArray subclass, we must override the count and objectAtIndex: methods

Any subclass of NSArray must override the primitive instance methods count and objectAtIndex :. These methods should work on the basis that you provide for the elements of the collection.


In concept, an array stores a number of data elements, each of which is accessible by index. NSArray expresses this abstract concept through its two primitive methods, count and objectAtIndex :. With these methods as a base, other derived methods are

Static Matrix Example

 class Months: NSArray { let months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ] override var count: Int { get { return months.count } } override func objectAtIndex(index: Int) -> AnyObject { assert(index < count, "The index is out of bounds") return months[index] } } 

Initialization

 let months = Months() println("My birthday month : \(months.objectAtIndex(6))") println("The last month of the year : \(months.lastObject)") 

Array with objects

 class MyArray: NSArray { var array: [AnyObject] = [] func populateWith(#objects: [AnyObject]) { self.array = objects } override var count: Int { get { return array.count } } override func objectAtIndex(index: Int) -> AnyObject { assert(index < count, "The index is out of bounds") return array[index] } } 

Initialization

 let fruits = MyArray() fruits.populateWith(objects: ["Apple", "Banana", "Orange", "Pear", "Cherry"]) println("Fruits count : \(fruits.count)") 

Subclass NSMutableArray

The same applies to NSArray, but we must override these methods:

  • number
  • objectAtIndex:
  • insertObject: atIndex:
  • removeObjectAtIndex:
  • AddObject:
  • removeLastObject
  • replaceObjectAtIndex: withObject:

I can add an example if necessary

Conclusion

We can subclass NSArray into swift (only when using the default initializer init ()), but we cannot (yet) use other initializers (e.g. initWithObjects: count :).

So, I agree with you, at the moment, the best solution is to subclass class clusters in objective-c

Class Cluster Documentation

NSArray Documentation

Hope that helps

0
source

Source: https://habr.com/ru/post/979787/


All Articles