스위프트 : nil에 대한 옵션 테스트
Xcode 6 Beta 4를 사용하고 있습니다. 옵션을 적절히 테스트하는 방법을 알 수없는 이상한 상황이 있습니다.
선택적 xyz가있는 경우 올바른 테스트 방법입니다.
if (xyz) // Do something
또는
if (xyz != nil) // Do something
문서는 첫 번째 방법으로 수행한다고 말하지만 때로는 두 번째 방법이 필요하며 컴파일러 오류를 생성하지 않지만 두 번째 방법은 컴파일러 오류를 생성한다는 것을 알았습니다.
내 구체적인 예는 신속하게 연결된 GData XML 파서를 사용하는 것입니다.
let xml = GDataXMLDocument(
XMLString: responseBody,
options: 0,
error: &xmlError);
if (xmlError != nil)
내가 방금 한 경우 여기 :
if xmlError
항상 true를 반환합니다. 그러나 내가 할 경우 :
if (xmlError != nil)
그런 다음 (Objective-C에서 작동하는 방식으로) 작동합니다.
GData XML과 누락 된 옵션을 처리하는 방식이 있습니까?
Xcode Beta 5에서는 더 이상 할 수 없습니다.
var xyz : NSString?
if xyz {
// Do something using `xyz`.
}
오류가 발생합니다.
프로토콜 'BooleanType.Protocol'을 준수하지 않습니다
다음 형식 중 하나를 사용해야합니다.
if xyz != nil {
// Do something using `xyz`.
}
if let xy = xyz {
// Do something using `xy`.
}
if
조건 내에서 다른 이름을 가진 변수에 할당하는 대신 다른 답변에 추가하려면 다음을 수행하십시오 .
var a: Int? = 5
if let b = a {
// do something
}
다음과 같은 변수 이름을 재사용 할 수 있습니다.
var a: Int? = 5
if let a = a {
// do something
}
이렇게하면 소재 변수 이름이 부족 해지는 것을 피할 수 있습니다 ...
이것은 Swift에서 지원되는 가변 그림자 를 활용 합니다.
옵션을 사용하는 가장 직접적인 방법 중 하나는 다음과 같습니다.
예를 들어 xyz
, 선택 유형 이라고 가정하십시오 Int?
.
if let possXYZ = xyz {
// do something with possXYZ (the unwrapped value of xyz)
} else {
// do something now that we know xyz is .None
}
이 방법 xyz
으로 값 이 포함되어 있는지 테스트 하고 있으면 해당 값으로 즉시 작업 할 수 있습니다.
컴파일러 오류와 관련하여 유형 UInt8
은 선택 사항이 아니므로 ( 'no'는 아님) 주로 변환 할 수 없습니다 nil
. 작업하는 변수가 선택 사항인지 확인한 후 변수로 취급하십시오.
Swift 3.0, 4.0
There are mainly two ways of checking optional for nil. Here are examples with comparison between them
1. if let
if let
is the most basic way to check optional for nil. Other conditions can be appended to this nil check, separated by comma. The variable must not be nil to move for the next condition. If only nil check is required, remove extra conditions in the following code.
Other than that, if x
is not nil, the if closure will be executed and x_val
will be available inside. Otherwise the else closure is triggered.
if let x_val = x, x_val > 5 {
//x_val available on this scope
} else {
}
2. guard let
guard let
can do similar things. It's main purpose is to make it logically more reasonable. It's like saying Make sure the variable is not nil, otherwise stop the function. guard let
can also do extra condition checking as if let
.
The differences are that the unwrapped value will be available on same scope as guard let
, as shown in the comment below. This also leads to the point that in else closure, the program has to exit the current scope, by return
, break
, etc.
guard let x_val = x, x_val > 5 else {
return
}
//x_val available on this scope
From swift programming guide
If Statements and Forced Unwrapping
You can use an if statement to find out whether an optional contains a value. If an optional does have a value, it evaluates to true; if it has no value at all, it evaluates to false.
So the best way to do this is
// swift > 3
if xyz != nil {}
and if you are using the xyz
in if statement.Than you can unwrap xyz
in if statement in constant variable .So you do not need to unwrap every place in if statement where xyz
is used.
if let yourConstant = xyz{
//use youtConstant you do not need to unwrap `xyz`
}
This convention is suggested by apple
and it will be followed by devlopers.
Although you must still either explicitly compare an optional with nil
or use optional binding to additionally extract its value (i.e. optionals are not implicitly converted into Boolean values), it's worth noting that Swift 2 has added the guard
statement to help avoid the pyramid of doom when working with multiple optional values.
In other words, your options now include explicitly checking for nil
:
if xyz != nil {
// Do something with xyz
}
Optional binding:
if let xyz = xyz {
// Do something with xyz
// (Note that we can reuse the same variable name)
}
And guard
statements:
guard let xyz = xyz else {
// Handle failure and then exit this code block
// e.g. by calling return, break, continue, or throw
return
}
// Do something with xyz, which is now guaranteed to be non-nil
Note how ordinary optional binding can lead to greater indentation when there is more than one optional value:
if let abc = abc {
if let xyz = xyz {
// Do something with abc and xyz
}
}
You can avoid this nesting with guard
statements:
guard let abc = abc else {
// Handle failure and then exit this code block
return
}
guard let xyz = xyz else {
// Handle failure and then exit this code block
return
}
// Do something with abc and xyz
Instead of if
, ternary operator might come handy when you want to get a value based on whether something is nil:
func f(x: String?) -> String {
return x == nil ? "empty" : "non-empty"
}
Another approach besides using if
or guard
statements to do the optional binding is to extend Optional
with:
extension Optional {
func ifValue(_ valueHandler: (Wrapped) -> Void) {
switch self {
case .some(let wrapped): valueHandler(wrapped)
default: break
}
}
}
ifValue
receives a closure and calls it with the value as an argument when the optional is not nil. It is used this way:
var helloString: String? = "Hello, World!"
helloString.ifValue {
print($0) // prints "Hello, World!"
}
helloString = nil
helloString.ifValue {
print($0) // This code never runs
}
You should probably use an if
or guard
however as those are the most conventional (thus familiar) approaches used by Swift programmers.
One option that hasn't specifically been covered is using Swift's ignored value syntax:
if let _ = xyz {
// something that should only happen if xyz is not nil
}
I like this since checking for nil
feels out of place in a modern language like Swift. I think the reason it feels out of place is that nil
is basically a sentinel value. We've done away with sentinels pretty much everywhere else in modern programming so nil
feels like it should go too.
var xyz : NSDictionary?
// case 1:
xyz = ["1":"one"]
// case 2: (empty dictionary)
xyz = NSDictionary()
// case 3: do nothing
if xyz { NSLog("xyz is not nil.") }
else { NSLog("xyz is nil.") }
This test worked as expected in all cases. BTW, you do not need the brackets ()
.
Now you can do in swift the following thing which allows you to regain a little bit of the objective-c if nil else
if textfieldDate.text?.isEmpty ?? true {
}
If you have conditional and would like to unwrap and compare, how about taking advantage of the short-circuit evaluation of compound boolean expression as in
if xyz != nil && xyz! == "some non-nil value" {
}
Granted, this is not as readable as some of the other suggested posts, but gets the job done and somewhat succinct than the other suggested solutions.
Also you can use Nil-Coalescing Operator
The
nil-coalescing operator
(a ?? b
) unwraps an optionala
if it containsa
value, or returnsa
default valueb
ifa
isnil
. The expression a is always of an optional type. The expressionb
must match the type that is stored insidea
.
let value = nullableValue ?? defaultValue
If nullableValue
is nil
, it automatically assigns value to defaultValue
Swift 5 Protocol Extension
Here is an approach using protocol extension so that you can easily inline an optional nil check:
public extension Optional {
var isNil: Bool {
guard case Optional.none = self else {
return false
}
return true
}
}
Usage
var myValue: String?
if !myValue.isNil {
// do something
}
참고URL : https://stackoverflow.com/questions/25097727/swift-testing-optionals-for-nil
'IT story' 카테고리의 다른 글
IIS Express에서 가상 디렉터리 만들기 (0) | 2020.07.13 |
---|---|
Android Studio IDE : 예외 발생시 중단 (0) | 2020.07.13 |
MySQL-SELECT WHERE field IN (하위 쿼리)-왜 느리게? (0) | 2020.07.13 |
부트 스트랩 반응 형 페이지에서 div를 가운데에 배치하는 방법 (0) | 2020.07.13 |
Jackson에서 Java 객체를 JsonNode로 변환 (0) | 2020.07.13 |