Since your Array extension puts no constraint on which types of arrays (element types) that can be used with it, .append(0) cannot be invoked; not all types can be converted into from integer literals. Hence, it's not weird that you cannot use .append(0) in the "generic" array extension, whereas you naturally can use it directly on an array that Swift can infer to have integer literal convertible elements, e.g. [Int]. Consider the following example:
var arr : [UInt8] = []
arr.append(0)
var arr2 : [String] = []
arr2.append(0) // error
In the example above, both arrays would have access to your extension dataWithPadding, but both can naturally not make use of arr.append(0) in the extension, hence the error message
Cannot invoke 'append' with an argument list of type '(Int)'
Now, a simple fix is to add a type constraint for the array elements to IntegerLiteralConvertible, after which you extension is valid, and accessible for all arrays that have elements which conform to IntegerLiteralConvertible.
extension Array where Element: IntegerLiteralConvertible {
func dataWithPadding(offset: Int, length: Int, paddingLength: Int) -> NSData {
var arr = Array(self[offset..<(offset + length)])
arr = arr.reverse()
for (var i = 0; i < paddingLength; i++) {
arr.append(0)
}
let d = NSData(bytesNoCopy: &arr, length: length)
return d
}
}
Alternatively, make use of the less general SignedNumberType, UnSignedIntegerType or IntegerType as type constraint for Element; these conform also to e.g. Comparable and Equatable, in case you'd like to compare and perform operations on your generic elements in the extension.
Finally note that you can naturally use your own custom protocol as type constraint for Element in your extension, allowing you to include additional blueprints (below, foo() method) accessible for your Element:s in the extension
protocol MyIntegerLiteralInitializableTypes: IntegerLiteralConvertible {
func foo()
}
extension MyIntegerLiteralInitializableTypes {
func foo() {
print("I am of type \(self.dynamicType)!")
}
}
/* For the Array<Type>:s you want to have access to .dataWithPadding,
extend those 'Type':s to MyIntegerLiteralInitializableTypes */
extension Int8 : MyIntegerLiteralInitializableTypes { }
extension UInt8 : MyIntegerLiteralInitializableTypes { }
extension Array where Element: MyIntegerLiteralInitializableTypes {
func dataWithPadding(offset: Int, length: Int, paddingLength: Int) -> NSData {
self.first?.foo() /* I am of type ...! */
var arr = Array(self[offset..<(offset + length)])
arr = arr.reverse()
for (var i = 0; i < paddingLength; i++) {
arr.append(0)
}
let d = NSData(bytesNoCopy: &arr, length: length)
return d
}
}
It's also probably a good idea to add @warn_unused_result to your dataWithPadding(...) function signature, as a call to it without assigning the return will yield a runtime exception ("... malloc: ...: pointer being freed was not allocated").