Parameter 'var' tidak digunakan lagi dan akan dihapus di Swift 3

120

Baiklah jadi saya baru saja memperbarui Xcode ke 7.3 dan sekarang saya mendapatkan peringatan ini:

Parameter 'var' tidak digunakan lagi dan akan dihapus di Swift 3

Cara memperbaikinya ketika saya perlu menggunakan var dalam fungsi ini:

public func getQuestionList(var language: String) -> NSArray {
    if self.data.count > 0 {
        if (language.isEmpty) {
            language = "NL"
        }
        return self.data.objectForKey("questionList" + language) as! NSArray
    }

    return NSArray()
}
SDW
sumber
6
Bagaimana denganpublic func getQuestionList(inout language: String) -> NSArray
TotoroTotoro
2
Tidak, ini bukan pengganti yang cocok. OP mungkin tidak ingin getQuestionada efek samping.
BallpointBen
5
Sejujurnya saya tidak tahu mengapa mereka bahkan mempertimbangkan untuk menghapus ini. Itu adalah salah satu fitur yang membuat swift mengagumkan!
Danny Bravo
Tidak pernah menggunakannya sendiri dan tidak mengerti keributannya.
Mike Taverne
@MikeTaverne (akhir balasan) Perhatikan fungsi berikut: func foo(_ bar: int) { /*use bar*/ bar+=1; foo(bar); }. Ini tidak mungkin tanpa var params. Anda juga perlu membuat var terpisah di dalam fungsi dan menyalin nilainya, atau menandai param sebagai inout. Yang pertama lambat, yang terakhir menyebabkan perilaku yang tidak terdefinisi. Banyak algoritme menggunakan rekursi seperti ini.
kevin

Jawaban:

82

Sudahkah Anda mencoba menetapkan ke var baru

public func getQuestionList(language: String) -> NSArray {
    var lang = language
    if self.data.count > 0 {
        if (lang.isEmpty) {
            lang = "NL"
        }
        return self.data.objectForKey("questionList" + lang) as! NSArray
    }

    return NSArray()
}
garanda
sumber
11
Tidak seperti yang saya pikir OP inginkan
belerang
6
Saya akan memahami pertanyaan OP dengan cara yang sama seperti @garana. OP tidak menggunakan inout dalam pertanyaan mereka, mereka hanya memutasi variabel yang sudah ada secara lokal .
Eric Aya
11
Sebenarnya ini adalah solusi yang tepat. Silakan lihat masalah evolusi Swift yang mengusulkan perubahan ini: github.com/apple/swift-evolution/blob/master/proposals/…
Scott Thompson
8
@TimVermeulen Semua orang ingin menggunakan bahasa progresif. Apple dapat mengembangkan bahasa mereka dengan banyak cara, bukan dengan mengubah sintaks setiap bulan. Seperti yang Anda ketahui, banyak dokumen dan cuplikan kode online telah kedaluwarsa atau ketinggalan zaman karena Apple. Pengembang harus datang ke situs ini untuk meminta bantuan dengan banyak pertanyaan bodoh berulang kali karenanya. Sintaksis harus solid sejak awal jika Apple ingin lebih banyak pengembang yang mahir melakukannya.
TomSawyer
25
Gunakan var bahasa = bahasa, jika Anda tidak ingin memperkenalkan nama variabel lain (yang merupakan keuntungan utama dari parameter var di tempat pertama imo)
Harris
102

Diskusi tentang penghapusan Var dari parameter fungsi sepenuhnya didokumentasikan dalam kiriman ini di GitHub: Hapus Parameter Var

Dalam dokumen tersebut Anda akan menemukan bahwa orang sering mengacaukan varparameter dengan inoutparameter. Sebuah varparameter hanya berarti bahwa parameter bisa berubah dalam konteks fungsi, sedangkan denganinout parameter nilai parameter pada titik pengembalian akan disalin dari fungsi dan dalam konteks pemanggil.

Cara yang benar untuk mengatasi masalah ini adalah dengan menghapus varparameter dan memasukkan varvariabel lokal . Di bagian atas rutin, salin nilai parameter ke variabel itu.

Tr0yJ
sumber
44
Saya sama sekali tidak mengerti perubahan ini, mengapa harus menulis baris lain untuk membuat var lokal yang bisa berubah lebih baik daripada hanya mendefinisikan param sebagai var?
Ross Barbish
Bagi saya perubahan ini bagus karena mengambil situasi di mana saya seharusnya menerapkan variabel lokal tetapi saya tidak melakukannya karena saya mengambil jalan keluar yang mudah dan menerima saran Swift (lama) untuk membuat parameter input var
dawid
1
Saya dengan @RossBarbish dalam hal ini. Jadi ... ini dihapus karena pengembang yang malas tidak dapat membedakan antara parameter inout dan var? Pfff ...
Danny Bravo
1
Ini tampaknya sangat tidak perlu ..., mereka seharusnya menyimpan kedua opsi tersebut.
Oscar Gomez
1
Mungkin swift juga mendeklarasikan variabel lokal di atas parameter di belakang layar. Sekarang kita harus melakukannya secara manual. Tidak ada perubahan performa, tapi kami kehilangan kenyamanan untuk membantu pemula dengan konsep yang sederhana.
mogelbuster
62

Cukup tambahkan satu baris ini di awal fungsi:

var language = language

dan kode Anda lainnya tidak akan berubah, seperti ini:

public func getQuestionList(language: String) -> NSArray {
    var language = language
    if self.data.count > 0 {
        if (language.isEmpty) {
            language = "NL"
        }
        return self.data.objectForKey("questionList" + language) as! NSArray
    }

    return NSArray()
}
Harris
sumber
5
Jawaban terbaik sejauh ini. Hanya perlu mengubah satu baris.
BallpointBen
Tapi terlihat begitu tidak wajar
@James
1
Saya merasa ini adalah jawaban terbaik karena namanya tetap sama. Mirip dengan bagaimana bahasa umum lainnya melakukannya.
eonist
1
@RiverSatya Mengapa tidak menggunakan parameter secara langsung?
Declan McKenna
1
Benar-benar saran yang luar biasa. Kami akan menerapkannya dengan cara ini di Swiftify :)
Crulex
13

Banyak orang menyarankan inoutparameter, tetapi sebenarnya bukan itu yang mereka rancang. Selain itu, itu tidak memungkinkan pemanggilan fungsi dengan letkonstanta, atau dengan string literal. Mengapa Anda tidak menambahkan nilai default ke tanda tangan fungsi?

public func getQuestionList(language language: String = "NL") -> NSArray {
    if data.count > 0 {
        return data.objectForKey("questionList" + language) as! NSArray
    } else {
        return NSArray()
    }
}

Pastikan untuk tidak memanggil getQuestionListdengan string kosong jika Anda menginginkan bahasa default, tetapi biarkan parameternya:

let list = getQuestionList() // uses the default "NL" language
Tim Vermeulen
sumber
3
Saya juga tidak mengerti mengapa semua orang menggunakan solusi masuk ketika OP tidak menggunakannya pada awalnya ...
Eric Aya
1
Mereka berasumsi bahwa var dan inout melakukan hal yang sama.
ryantxr
2

Cepat 4

public func getQuestionList(language: inout String) -> NSArray {
    if self.data.count > 0 {
        if (language.isEmpty) {
            language = "NL"
        }
        return self.data.objectForKey("questionList" + language) as! NSArray
    }

    return NSArray()
}

getQuestionList(language: &someString)

Dalam beberapa kasus, seperti yang saya alami (dengan pengaturan yang lebih kompleks yang melibatkan array), membuat properti baru di dalam metode dan mengubah properti itu mungkin tidak selalu berfungsi. Belum lagi, Anda mengacaukan metode alih-alih hanya menambahkan inoutke parameter dan &argumennya, yang untuk tujuan sintaks ini dibuat.

bsod
sumber
1
public func getQuestionList(language: inout String) -> NSArray {
if self.data.count > 0 {
    if (language.isEmpty) {
        language = "NL"
    }
    return self.data.objectForKey("questionList" + language) as! NSArray
}

return NSArray()

}

Abdul Rahman Khan
sumber
0

Menurut saya jawaban @Harris dan @garanda adalah pendekatan terbaik.

Bagaimanapun, dalam kasus Anda, var tidak diperlukan, Anda dapat melakukan:

public func getQuestionList(language: String) -> NSArray {
    if self.data.count > 0 {
        return self.data.objectForKey("questionList" + (language.isEmpty ? "NL" : language)) as! NSArray
    }
    return NSArray()
}
Simone Pistecchia
sumber
0

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html

Parameter Masuk-Keluar

Parameter fungsi adalah konstanta secara default. Mencoba mengubah nilai parameter fungsi dari dalam tubuh fungsi itu menghasilkan kesalahan waktu kompilasi. Ini berarti Anda tidak dapat mengubah nilai parameter secara tidak sengaja. Jika Anda ingin sebuah fungsi mengubah nilai parameter, dan Anda ingin perubahan tersebut tetap ada setelah panggilan fungsi berakhir, tetapkan parameter itu sebagai parameter masuk-keluar.

Anda menulis parameter masuk-keluar dengan menempatkan kata kunci masuk tepat sebelum jenis parameter. Parameter masuk-keluar memiliki nilai yang diteruskan ke fungsi, dimodifikasi oleh fungsi, dan dikirim keluar fungsi untuk menggantikan nilai asli. Untuk pembahasan mendetail tentang perilaku parameter masuk-keluar dan pengoptimalan compiler terkait, lihat Parameter Masuk-Keluar.

Anda hanya dapat mengirimkan variabel sebagai argumen untuk parameter masuk-keluar. Anda tidak dapat meneruskan konstanta atau nilai literal sebagai argumen, karena konstanta dan literal tidak dapat diubah. Anda menempatkan ampersand (&) tepat sebelum nama variabel ketika Anda meneruskannya sebagai argumen ke parameter masuk-keluar, untuk menunjukkan bahwa itu dapat dimodifikasi oleh fungsi.

CATATAN

Parameter masuk-keluar tidak boleh memiliki nilai default, dan parameter variadic tidak dapat ditandai sebagai masuk.

Berikut adalah contoh fungsi yang disebut swapTwoInts ( : :), yang memiliki dua parameter bilangan bulat masuk-keluar yang disebut a dan b:

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

The swapTwoInts ( : :) hanya menukar nilai b menjadi a, dan nilai a menjadi b. Fungsi melakukan pertukaran ini dengan menyimpan nilai a dalam konstanta sementara yang disebut temporaryA, menetapkan nilai b ke a, dan kemudian menetapkan sementaraA ke b.

Anda dapat memanggil fungsi swapTwoInts ( : :) dengan dua variabel bertipe Int untuk menukar nilainya. Perhatikan bahwa nama someInt dan anotherInt diawali dengan ampersand saat diteruskan ke fungsi swapTwoInts ( : :):

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// Prints "someInt is now 107, and anotherInt is now 3"

Contoh di atas menunjukkan bahwa nilai asli someInt dan anotherInt dimodifikasi oleh fungsi swapTwoInts ( : :), meskipun awalnya ditentukan di luar fungsi.

CATATAN

Parameter masuk-keluar tidak sama dengan mengembalikan nilai dari suatu fungsi. Contoh swapTwoInts di atas tidak mendefinisikan tipe pengembalian atau mengembalikan nilai, tetapi masih mengubah nilai someInt dan anotherInt. Parameter masuk-keluar adalah cara alternatif agar suatu fungsi memiliki efek di luar ruang lingkup badan fungsinya.

Mustafa Mohammed
sumber
0

Ini ide lainnya. Kasus penggunaan saya adalah untuk melewatkan array string untuk ditambahkan ke dalamnya, yang array harus dilewatkan secara bergilir. Saya juga tidak ingin mendapat status di kelas saya untuk ini. Jadi saya membuat kelas yang menampung array dan meneruskannya. Bergantung pada kasus penggunaan Anda, mungkin tampak konyol memiliki kelas yang hanya berisi satu variabel itu.

private class StringBuilder {
    var buffer: [String] = []

    func append(_ str: String) {
        buffer.append(str)
    }

    func toString() -> String {
        return buffer.joined()
    }
}

Saya hanya menggunakan appenddan joinedmetode pada array sehingga mudah untuk mengubah tipe dengan sedikit perubahan lain pada kode saya.

Beberapa contoh penggunaan:

private func writeMap(map: LevelMap, url: URL) -> Bool {
    let buffer = StringBuilder()

    if !writeHeader(map: map, buffer: buffer) {
        return false
    }
    if !writeFloors(map: map, buffer: buffer) {
        return false
    }

    let content = buffer.toString()
    do {
        try content.write(to: url, atomically: true, encoding: .utf8)
        return true
    } catch {}
    return false
}

private func writeHeader(map: LevelMap, buffer: StringBuilder) -> Bool {
    buffer.append("something here ...\n")
    return true
}
webjprgm
sumber
Jawaban saya adalah jika Anda INGIN nilai asli seperti yang dilihat oleh pemanggil untuk dimodifikasi. Jika Anda hanya ingin dapat menetapkan ulang nilai secara lokal tetapi tidak memengaruhi penelepon, jawaban lain di atas akan mengatasinya.
webjprgm