'var' parametreleri kullanımdan kaldırıldı ve Swift 3'te kaldırılacak


120

Pekala, Xcode'u 7.3'e güncelliyorum ve şimdi şu uyarıyı alıyorum:

'var' parametreleri kullanımdan kaldırıldı ve Swift 3'te kaldırılacak

Bu işlevde var'ı kullanmam gerektiğinde bunu nasıl düzeltebilirim:

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()
}

6
Peki yapublic func getQuestionList(inout language: String) -> NSArray
TotoroTotoro

2
Hayır, bu uygun bir yedek değil. OP muhtemelen getQuestionherhangi bir yan etkiye sahip olmak istemiyor .
BallpointBen

5
Dürüst olmak gerekirse, bunu neden kaldırmayı düşündükleri hakkında hiçbir fikrim yok. Swift'i harika yapan özelliklerden biriydi!
Danny Bravo

Kendim hiç kullanmadım ve yaygarayı anlamadım.
Mike Taverne

@MikeTaverne (geç yanıt) aşağıdaki işlevi göz önünde bulundurun: func foo(_ bar: int) { /*use bar*/ bar+=1; foo(bar); }. Bu, var parametreler olmadan imkansızdır. Fonksiyon içinde ayrı bir değişken oluşturmanız ve değeri kopyalamanız veya paramı inout olarak işaretlemeniz gerekir. İlki yavaştır, ikincisi tanımlanmamış davranışlara neden olur. Çoğu algoritma bunun gibi özyinelemeyi kullanır.
Kevin

Yanıtlar:


82

Yeni bir değişken atamayı denediniz mi?

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()
}

11
OP'nin istediğini düşündüğüm pek de bu değil
kükürt

6
OP'nin sorusunu @garana ile aynı şekilde anlardım. OP inout'u sorgularında kullanmaz, sadece önceden var olan bir değişkeni yerel olarak değiştirirler .
Eric Aya

11
Aslında bu doğru çözüm. Lütfen bu değişikliği öneren Swift evrim sorununa bakın: github.com/apple/swift-evolution/blob/master/proposals/…
Scott Thompson

8
@TimVermeulen Herkes ilerici bir dil kullanmak ister. Apple, dilini her ay sözdizimini değiştirerek değil birçok şekilde geliştirebilir. Bildiğiniz gibi, bir ton çevrimiçi belge ve kod parçacığı, Apple nedeniyle süresi doluyor veya güncelliğini yitiriyor. Geliştiricilerin bu siteye gelip birçok aptalca soruyla defalarca yardım istemesi gerekiyor. Apple daha fazla geliştiricinin bunda iyi olmasını istiyorsa sözdizimi baştan itibaren sağlam olmalıdır.
TomSawyer

25
Başka bir değişken adı eklemek istemiyorsanız, var language = language kullanın (ki bu, imo ilk etapta var parametresinin ana avantajıdır)
Harris

102

Var'ın bir işlev parametresinden kaldırılmasına ilişkin tartışma, GitHub'daki bu sunumda tam olarak belgelenmiştir: Var Parametrelerini Kaldır

Bu belgede, insanların genellikle varparametreleri inoutparametrelerle karıştırdıklarını göreceksiniz . Bir varparametre basitçe parametrenin işlev bağlamında değiştirilebilir olduğu anlamına gelirken, bir inoutparametre ile dönüş noktasındaki parametrenin değeri işlevin dışına ve arayanın bağlamına kopyalanacaktır.

Bu sorunu çözmenin doğru yolu var, parametreden çıkarmak ve yerel bir vardeğişken sunmaktır. Rutinin en üstünde, parametrenin değerini bu değişkene kopyalayın.


44
Bu değişikliği hiç anlamıyorum, neden değişken bir yerel değişken oluşturmak için başka bir satır yazmak zorunda kalmak, paramı bir var olarak tanımlamaktan daha iyi olabilir?
Ross Barbish

Benim için bu değişiklik iyi, çünkü yerel bir değişken uygulamam gereken durumları alıyor, ancak kolay yolu seçip (eski) Swift'in girdi parametresini değişken yapma önerisini kabul
ettiğim için yapmadım

1
Bu konuda @RossBarbish ile birlikteyim. Yani ... bu kaldırılıyor çünkü tembel geliştiriciler inout ve var parametreleri arasında ayrım yapamıyor? Pfff ...
Danny Bravo

1
Bu çok gereksiz görünüyor ... her iki seçeneği de tutmaları gerekirdi.
Oscar Gomez

1
Muhtemelen swift, yine de sahne arkasında parametrenin üstünde bir yerel değişken ilan ediyordu. Şimdi bunu manuel olarak yapmalıyız. Performansta değişiklik yok, ancak yeni başlayanlara basit bir konseptle yardımcı olma kolaylığını kaybettik.
mogelbuster

62

İşlevin başına şu satırı ekleyin:

var language = language

ve kodunuzun geri kalanı değişmeden kalabilir, örneğin:

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()
}

5
Şimdiye kadarki en iyi cevap. Yalnızca bir satırın değiştirilmesi gerekir.
BallpointBen

Ama çok doğal görünmüyor @James
asyncwait

1
Aynı adı taşıdığı için bunun en iyi cevap olduğunu düşünüyorum. Diğer yaygın dillerin yaptığı gibi.
eonist

1
@RiverSatya Neden parametreyi doğrudan kullanmıyorsunuz?
Declan McKenna

1
Gerçekten harika bir öneri. Swiftify'da bu şekilde uygulayacağız :)
Crulex

13

Pek çok insan bir inoutparametre öneriyor , ancak aslında tasarlandıkları şey bu değil. Ayrıca, işlevin bir letsabitle veya bir dizge ile çağrılmasına izin vermez . Neden varsayılan değeri işlev imzasına eklemiyorsunuz?

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

getQuestionListVarsayılan dili istiyorsanız boş dizeyle çağırmadığınızdan emin olun , ancak parametreyi dışarıda bırakın:

let list = getQuestionList() // uses the default "NL" language

3
Ayrıca OP başlangıçta bunu kullanmıyorken neden herkesin başlangıç ​​çözümüne atladığını anlamıyorum ...
Eric Aya

1
Var ve inout'un aynı şeyi yaptığını varsayıyorlardı.
ryantxr

2

Swift 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)

Bazı durumlarda, deneyimlediğim gibi (dizileri içeren daha karmaşık kurulumlarda), yöntem içinde yeni bir özellik oluşturmak ve bu özelliği değiştirmek her zaman işe yaramayabilir. Bahsetmiyorum bile, basitçe inoutbir parametreye ve &onun argümanına eklemek yerine yöntemi karıştırıyorsunuz , bu sözdiziminin bunun için yaratıldığı da budur.



0

Bence @Harris ve @garanda cevapları en iyi yaklaşım.

Her neyse, sizin durumunuzda bir değişkene gerek yok, şunları yapabilirsiniz:

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

0

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

In-Out Parametreleri

İşlev parametreleri varsayılan olarak sabittir. Bir işlev parametresinin değerini o işlevin gövdesinden değiştirmeye çalışmak, derleme zamanı hatasıyla sonuçlanır. Bu, yanlışlıkla bir parametrenin değerini değiştiremeyeceğiniz anlamına gelir. Bir işlevin bir parametrenin değerini değiştirmesini istiyorsanız ve bu değişikliklerin işlev çağrısı bittikten sonra da devam etmesini istiyorsanız, bunun yerine bu parametreyi bir in-out parametresi olarak tanımlayın.

İnout anahtar sözcüğünü bir parametrenin türünün hemen önüne yerleştirerek bir in-out parametresi yazarsınız. Bir in-out parametresi, işleve iletilen, işlev tarafından değiştirilen ve orijinal değeri değiştirmek için işlevden geri gönderilen bir değere sahiptir. Giriş-çıkış parametrelerinin davranışına ve ilgili derleyici optimizasyonlarına ilişkin ayrıntılı bir tartışma için, bkz. Giriş-Çıkış Parametreleri.

Yalnızca bir in-out parametresi için bağımsız değişken olarak bir değişkeni iletebilirsiniz. Değişken olarak bir sabit veya değişmez değer iletemezsiniz, çünkü sabitler ve değişmezler değiştirilemez. İşlev tarafından değiştirilebileceğini belirtmek için, bir in-out parametresine bağımsız değişken olarak ilettiğinizde, bir değişken adının hemen önüne bir ve işareti (&) koyarsınız.

NOT

In-out parametrelerinin varsayılan değerleri olamaz ve variadic parametreler inout olarak işaretlenemez.

Aşağıda , a ve b adında iki giriş-çıkış tamsayı parametresine sahip swapTwoInts ( : :) adlı bir fonksiyon örneği verilmiştir :

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

SwapTwoInts ( : :) işlevi basitçe b'nin değerini a'ya ve a'nın değerini b'ye değiştirir. İşlev, bu takas işlemini, a'nın değerini geçiciA adı verilen geçici bir sabit içinde saklayarak, b'nin değerini a'ya atayarak ve ardından geçici A'yı b'ye atayarak gerçekleştirir.

Değerlerini takas etmek için swapTwoInts ( : :) işlevini Int türünde iki değişkenle çağırabilirsiniz . SwapTwoInts ( : :) işlevine aktarıldıklarında someInt ve anotherInt adlarının önünde bir ve işareti bulunduğunu unutmayın :

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"

Yukarıdaki örnek, someInt ve anotherInt'in orijinal değerlerinin, başlangıçta işlevin dışında tanımlanmış olsalar bile swapTwoInts ( : :) işlevi tarafından değiştirildiğini gösterir .

NOT

Giriş-çıkış parametreleri, bir fonksiyondan değer döndürmekle aynı şey değildir. Yukarıdaki swapTwoInts örneği bir dönüş türü tanımlamaz veya bir değer döndürmez, ancak yine de someInt ve anotherInt değerlerini değiştirir. Giriş-çıkış parametreleri, bir işlevin işlev gövdesinin kapsamı dışında bir etkiye sahip olması için alternatif bir yoldur.


0

İşte başka bir fikir. Benim kullanım durumum, ona eklenecek bir dizge dizisinin etrafından geçmekti, bunun için dizinin değişken olarak iletilmesi gerekiyordu. Bunun için de sınıfımda devlet olmasını istemedim. Bu yüzden diziyi tutan bir sınıf yaptım ve onu geçirdim. Kullanım durumunuza bağlı olarak, sadece o değişkeni tutan bir sınıfa sahip olmak aptalca görünebilir.

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

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

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

Dizide yalnızca appendve joinedyöntemleri kullanıyorum, bu nedenle kodumda en az başka değişiklikle türü değiştirmek kolaydı.

Bazı örnek kullanımlar:

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
}

Cevabım, arayan tarafından görüldüğü şekliyle orijinal değerin değiştirilmesini İSTİYORSANIZ. Sadece değeri yerel olarak yeniden atayabilmek istiyorsanız, ancak arayanı etkilemesini istemiyorsanız, yukarıdaki diğer cevaplar bununla ilgilenir.
webjprgm
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.