Q: Is there a better way to create an index of an array? I made up a method to add a variable rankto an array of structs.
The array friutsArrayis created like in the function makeFriuts(). After that, the data gets sorted and according to this, every item gets a rank, respectively index.
In the end I need the FriutsWithRankstruct like it is.
But I´m wondering if there is a better, more effective way to to that. Maybe by even skipping the whole Friuts struct:
struct Friuts {
    var name: String
    var price: Double
}

struct FriutsWithRank {
    var name: String
    var price: Double
    var rank: Int
}

var friutsArray = [Friuts]()

func makeFriuts() {
    friutsArray.append(Friuts(name: "mango", price: 1.2))
    friutsArray.append(Friuts(name: "banana", price: 0.79))
    friutsArray.append(Friuts(name: "orange", price: 2.2))
}

func makeFriutsWithRank(data: [Friuts]) -> [FriutsWithRank] {

    let dataSorted = data.sorted { $1.price < $0.price }

    var datatoappend = [FriutsWithRank]()

    var i = 0
    dataSorted.forEach { fruit in
        i += 1
        let name = fruit.name
        let price = fruit.price
        let rank = i

        let result = FriutsWithRank(name: name, price: price, rank: rank)

        datatoappend.append(result)
    }
    return datatoappend
}

let friutsArrayWithRank = makeFriutsWithRank(data: friutsArray) 

With more effective i mean not necessarily less code. I think the two arrays are now created with two iterations. Is it possible to skip the whole Fruits struct and work just with one struct and one iteration?.

A: I have applied some modification on your code, please read the inline comments. Not much more optimised, but more readable for sure.
// Typo fixed + it is a single Fruit, not Fruits
struct Fruit {
    var name: String
    var price: Double
}


struct FruitsWithRank {
    // You already have a variable holding name and price, Friut
    // Lets just reuse Fruit object
    var fruit: Fruits
    var rank: Int
}

var fruits = [Fruit]()

func makeFruits() {
    fruits.append(Fruit(name: "mango", price: 1.2))
    fruits.append(Fruit(name: "banana", price: 0.79))
    fruits.append(Fruit(name: "orange", price: 2.2))
}

func makeFruitsWithRank(data: [Fruits]) -> [FruitsWithRank] {

    let dataSorted = data.sorted { $1.price < $0.price }
    var datatoappend = [FruitsWithRank]()
    // Use `enumerated` to get index and the object straight away
    for (index, fruit) in dataSorted.enumerated() {
        // Just init your `FruitsWithRank` with the fruit and the index
        let rankedFruit = FruitsWithRank(fruit: fruit, rank: index)
        // Add to your array
        datatoappend.append(rankedFruit)
    } 

    return datatoappend
}

let fruitsWithRank = makeFruitsWithRank(data: fruitsArray) 

EDIT:
Following the edits of your question, i have applied some changes. If you need FruitsWithRank having name and price, you can just create tuples with name and price, and create an array straight away without any loops or appends. You can omit the makeFruitsWithRank function, and sort, enumerate and create your types straight on the tuple array.
struct FruitsWithRank {
    var rank: Int
    var name: String
    var price: Double
}

let rankedFruits: [FruitsWithRank] = [
        (name: "mango", price: 1.2), 
        (name: "banana", price: 0.79), 
        (name: "orange", price: 2.2)]
        .sorted { $0.price < $1.price }
        .enumerated()
        .map({ return FruitsWithRank(rank: $0 + 1, name: $1.name, price: $1.price) })


A: In the end this isn't much more efficient than your code, but it is more compact:
func makeFriutsWithRank(data: [Friuts]) -> [FriutsWithRank] {

    let dataMapped = data.sorted { $1.price < $0.price }
        .enumerated()
        .map { FriutsWithRank(name: $1.name, price: $1.price, rank: $0 + 1) }

    return dataMapped
}


A: Is it really necassary to have Struct? Because you already have sorted, the index can serve as rank. 
