What in the World is an “Escaping Closure” in Swift? – Andrew Bancroft

https://stackoverflow.com/a/35046681/3151712For-In Loops

You use the forin loop to iterate over a sequence, such as items in an array, ranges of numbers, or characters in a string.

let names = [“Anna”, “Alex”, “Brian”, “Jack”]
for name in names {
   print(“Hello, (name)!”)
}
// Hello, Anna!
// Hello, Alex!
// Hello, Brian!
// Hello, Jack!

You can also iterate over a dictionary to access its key-value pairs. Each item in the dictionary is returned as a (key, value) tuple when the dictionary is iterated, and you can decompose the (key, value) tuple’s members as explicitly named constants for use within the body of the forin loop. In the code example below, the dictionary’s keys are decomposed into a constant called animalName, and the dictionary’s values are decomposed into a constant called legCount.

let numberOfLegs = [“spider”: 8, “ant”: 6, “cat”: 4]
for (animalName, legCount) in numberOfLegs {
   print(“(animalName)s have (legCount) legs”)
}
// ants have 6 legs
// spiders have 8 legs
// cats have 4 legs

for index in 1…5 {
   print(“(index) times 5 is (index * 5)”)
}
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25

If you don’t need each value from a sequence, you can ignore the values by using an underscore in place of a variable name.

let base = 3
let power = 10
var answer = 1
for _ in 1…power {
   answer *= base
}
print(“(base) to the power of (power) is (answer)”)
// Prints “3 to the power of 10 is 59049”

let minutes = 60
for tickMark in 0..<minutes {
   // render the tick mark each minute (60 times)
}

stride(from:to:by:) function

let minuteInterval = 5
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
   // render the tick mark every 5 minutes (0, 5, 10, 15 … 45, 50, 55)
}

Closed ranges are also available, by using stride(from:through:by:) instead:

let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
   // render the tick mark every 3 hours (3, 6, 9, 12)
}

While Loops

  • while evaluates its condition at the start of each pass through the loop.
  • repeatwhile evaluates its condition at the end of each pass through the loop.

While

A while loop starts by evaluating a single condition. If the condition is true, a set of statements is repeated until the condition becomes false.

while square < finalSquare {
   // roll the dice
   
}

Repeat-While

The other variation of the while loop, known as the repeatwhile loop, performs a single pass through the loop block first, before considering the loop’s condition. It then continues to repeat the loop until the condition is false.

repeat {
   // move up or down for a snake or ladder
  
} while square < finalSquare

Conditional Statements

If

if temperatureInFahrenheit <= 32 {
   print(“It’s very cold. Consider wearing a scarf.”)
} else if temperatureInFahrenheit >= 86 {
   print(“It’s really warm. Don’t forget to wear sunscreen.”)
} else {
   print(“It’s not that cold. Wear a t-shirt.”)
}
// Prints “It’s really warm. Don’t forget to wear sunscreen.”

Switch

let someCharacter: Character = “z”
switch someCharacter {
case “a”:
   print(“The first letter of the alphabet”)
case “z”:
   print(“The last letter of the alphabet”)
default:
   print(“Some other character”)
}
// Prints “The last letter of the alphabet”

No Implicit Fallthrough

In contrast with switch statements in C and Objective-C, switch statements in Swift do not fall through the bottom of each case and into the next one by default. Instead, the entire switch statement finishes its execution as soon as the first matching switch case is completed, without requiring an explicit breakstatement.

NOTE

Although break is not required in Swift, you can use a break statement to match and ignore a particular case or to break out of a matched case before that case has completed its execution.

The body of each case must contain at least one executable statement. It is not valid to write the following code, because the first case is empty:

let anotherCharacter: Character = “a”
switch anotherCharacter {
case “a”: // Invalid, the case has an empty body
case “A”:
   print(“The letter A”)
default:
   print(“Not the letter A”)
}
// This will report a compile-time error.

To make a switch with a single case that matches both "a" and "A", combine the two values into a compound case, separating the values with commas.

let anotherCharacter: Character = “a”
switch anotherCharacter {
case “a”, “A”:
   print(“The letter A”)
default:
   print(“Not the letter A”)
}
// Prints “The letter A”

Interval Matching

let approximateCount = 62
let countedThings = “moons orbiting Saturn”
let naturalCount: String
switch approximateCount {
case 0:
   naturalCount = “no”
case 1..<5:
   naturalCount = “a few”
case 5..<12:
   naturalCount = “several”
case 12..<100:
   naturalCount = “dozens of”
case 100..<1000:
   naturalCount = “hundreds of”
default:
   naturalCount = “many”
}
print(“There are (naturalCount) (countedThings).”)
// Prints “There are dozens of moons orbiting Saturn.”

Tuples

You can use tuples to test multiple values in the same switch statement. use the underscore character (_), also known as the wildcard pattern, to match any possible value.

let somePoint = (1, 1)
switch somePoint {
case (0, 0):
   print(“(somePoint) is at the origin”)
case (_, 0):
   print(“(somePoint) is on the x-axis”)
case (0, _):
   print(“(somePoint) is on the y-axis”)
case (-2…2, -2…2):
   print(“(somePoint) is inside the box”)
default:
   print(“(somePoint) is outside of the box”)
}
// Prints “(1, 1) is inside the box”

n fact, the point (0, 0) could match all four of the cases in this example. However, if multiple matches are possible, the first matching case is always used. The point (0, 0) would match case (0, 0) first, and so all other matching cases would be ignored.

Value Bindings

let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
   print(“on the x-axis with an x value of (x)”)
case (0, let y):
   print(“on the y-axis with a y value of (y)”)
case let (x, y):
   print(“somewhere else at ((x), (y))”)
}
// Prints “on the x-axis with an x value of 2”

After the temporary constants are declared, they can be used within the case’s code block. 

This switch statement does not have a default case. The final case, case let (x, y), declares a tuple of two placeholder constants that can match any value. Because anotherPoint is always a tuple of two values, this case matches all possible remaining values, and a default case is not needed to make the switch statement exhaustive.

Where

A switch case can use a where clause to check for additional conditions.

let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
   print(“((x), (y)) is on the line x == y”)
case let (x, y) where x == -y:
   print(“((x), (y)) is on the line x == -y”)
case let (x, y):
   print(“((x), (y)) is just some arbitrary point”)
}
// Prints “(1, -1) is on the line x == -y”

Compound Cases

Multiple switch cases that share the same body can be combined by writing several patterns after case, with a comma between each of the patterns.

let someCharacter: Character = “e”
switch someCharacter {
case “a”, “e”, “i”, “o”, “u”:
   print(“(someCharacter) is a vowel”)
case “b”, “c”, “d”, “f”, “g”, “h”, “j”, “k”, “l”, “m”,
    “n”, “p”, “q”, “r”, “s”, “t”, “v”, “w”, “x”, “y”, “z”:
   print(“(someCharacter) is a consonant”)
default:
   print(“(someCharacter) is not a vowel or a consonant”)
}
// Prints “e is a vowel”

let stillAnotherPoint = (9, 0)
switch stillAnotherPoint {
case (let distance, 0), (0, let distance):
   print(“On an axis, (distance) from the origin”)
default:
   print(“Not on an axis”)
}
// Prints “On an axis, 9 from the origin”

Control Transfer Statements

  • continue
  • break
  • fallthrough
  • return
  • throw

Continue

The continue statement tells a loop to stop what it is doing and start again at the beginning of the next iteration through the loop.

let puzzleInput = “great minds think alike”
var puzzleOutput = “”
let charactersToRemove: [Character] = [“a”, “e”, “i”, “o”, “u”, “ ”]
for character in puzzleInput {
   if charactersToRemove.contains(character) {
       continue
   } else {
       puzzleOutput.append(character)
   }
}
print(puzzleOutput)
// Prints “grtmndsthnklk”

Break

The break statement ends execution of an entire control flow statement immediately. The break statement can be used inside a switch or loop statement when you want to terminate the execution of the switch or loop statement earlier than would otherwise be the case.

Break in a Loop Statement

When used inside a loop statement, break ends the loop’s execution immediately and transfers control to the code after the loop’s closing brace (}). No further code from the current iteration of the loop is executed, and no further iterations of the loop are started.

Break in a Switch Statement

When used inside a switch statement, break causes the switch statement to end its execution immediately and to transfer control to the code after the switch statement’s closing brace (}).

Fallthrough

In Swift,the entire switch statement completes its execution as soon as the first matching case is completed. By contrast, C requires you to insert an explicit break statement at the end of every switch case to prevent fallthrough

let integerToDescribe = 5
var description = “The number (integerToDescribe) is”
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
   description += “ a prime number, and also”
   fallthrough
default:
   description += “ an integer.”
}
print(description)
// Prints “The number 5 is a prime number, and also an integer.”

NOTE

The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior.

Labeled Statements

gameLoop: while square != finalSquare {
   diceRoll += 1
   if diceRoll == 7 { diceRoll = 1 }
   switch square + diceRoll {
   case finalSquare:
       // diceRoll will move us to the final square, so the game is over
       break gameLoop
   case let newSquare where newSquare > finalSquare:
       // diceRoll will move us beyond the final square, so roll again
       continue gameLoop
   default:
       // this is a valid move, so find out its effect
       square += diceRoll
       square += board[square]
   }
}
print(“Game over!”)

Early Exit

A guard statement, like an if statement, executes statements depending on the Boolean value of an expression. You use a guard statement to require that a condition must be true in order for the code after the guard statement to be executed. Unlike an if statement, a guard statement always has an else clause—the code inside the else clause is executed if the condition is not true.

func greet(person: [String: String]) {
   guard let name = person[“name”] else {
       return
   }
   
   print(“Hello (name)!”)
   
   guard let location = person[“location”] else {
       print(“I hope the weather is nice near you.”)
       return
   }
   
   print(“I hope the weather is nice in (location).”)
}
greet(person: [“name”: “John”])
// Prints “Hello John!”
// Prints “I hope the weather is nice near you.”
greet(person: [“name”: “Jane”, “location”: “Cupertino”])
// Prints “Hello Jane!”
// Prints “I hope the weather is nice in Cupertino.”

If the guard statement’s condition is met, code execution continues after the guard statement’s closing brace. Any variables or constants that were assigned values using an optional binding as part of the condition are available for the rest of the code block that the guard statement appears in.

If that condition is not met, the code inside the else branch is executed. That branch must transfer control to exit the code block in which the guard statement appears. It can do this with a control transfer statement such as return, break, continue, or throw, or it can call a function or method that doesn’t return, such as fatalError(_:file:line:).

참고

ref) https://ericcerney.com/swift-guard-statement/

optional binding ref) https://stackoverflow.com/a/35046681/3151712

Checking API Availability

Swift has built-in support for checking API availability, which ensures that you don’t accidentally use APIs that are unavailable on a given deployment target.

You use an availability condition in an if or guard statement to conditionally execute a block of code.

if #available(iOS 10, macOS 10.12, *) {
   // Use iOS 10 APIs on iOS, and use macOS 10.12 APIs on macOS
} else {
   // Fall back to earlier iOS and macOS APIs
}

if #available(platform name version, …, *) {
   statements to execute if the APIs are available
} else {
   fallback statements to execute if the APIs are unavailable
}

How do I send a POST request as a JSON?

google oauth나 gcm, fcm를 사용하는 경우 app안에(실제로도 app폴더안에) google-services.json화일을 포함해야한다. firebase서비스를 사용하는 경우 각종 정보를 ( debug시 사용한 sha1 키값, google play에 업로드하고 받은 sha1키값 포함) 기입하고 난후에 json 화일을 만들고 그것을 프로젝트에 포함한다.

https://play.google.com/apps/publish/ 를 통해 google play 사이트에 들어간다. 

들어가 보면 app release시에 새로 sha1가 만들어진것을 알수 있다.

image

이 새로 만들어진 sha1를 이용하여 https://console.developers.google.com/apis/ 에서 해당 sha1를 이용한 새로운 credentials를 만들어주어야 한다. 

이 새로운 credential을 만드는 과정은 배포된 app은 새로 만들어진 sha1를 이용하여 api 서비스를 이용하기 때문에 api 접근 통로를 하나더 만드는 과정이다.

image
image
image

When you upload an apk to the play store then play store creates a new SHA1 key called “App signing certificate”. You get that SHA1 and save in your console or firebase account (as you need).

New SHA1 will be found at Released Management->App Sigining on your play console.

or

when you build signed apk with your filename.jks it has different SHA than your debug apk, put these SHA which is generated by signed apk in Firebase nd update it and again download json from firebase and override existing json from your android studio.

ref) https://stackoverflow.com/questions/35561657/sign-in-with-google-for-android-not-working-in-release-apk