페이지

2017년 11월 3일 금요일

Dynamically Sized Table View Header or Footer Using Auto Layout

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // Dynamic sizing for the header view
    if let headerView = tableView.tableHeaderView {
        let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
        var headerFrame = headerView.frame

        // If we don't have this check, viewDidLayoutSubviews() will get
        // repeatedly, causing the app to hang.

        if height != headerFrame.size.height {
            headerFrame.size.height = height
            headerView.frame = headerFrame
            tableView.tableHeaderView = headerView
        }
    }
}


http://collindonnell.com/2015/09/29/dynamically-sized-table-view-header-or-footer-using-auto-layout/

2017년 10월 22일 일요일

notice: distributing ad hoc ipa

Building adhoc ipa file, You must check "Manually manage signing".
and you just choose its adhoc app provisioning file and certificate

(x) Automatically manage signing
(o) Manually manage signing


2017년 10월 20일 금요일

uitableview header top spacing issue

self.automaticallyAdjustScrollViewInsets = false


2017년 10월 10일 화요일

content hugging vs content compression resistance priority

https://stackoverflow.com/questions/15850417/cocoa-autolayout-content-hugging-vs-content-compression-resistance-priority/16281229#16281229

down voteaccepted
Quick summary of the concepts:
  • Hugging => content does not want to grow
  • Compression Resistance => content does not want to shrink
and an example:
Say you've got button like this:
[       Click Me      ]
and you've pinned the edges to a larger superview with priority 500.
Then, if Hugging priority > 500 it'll look like this:
[Click Me]
If Hugging priority < 500 it'll look like this:
[       Click Me      ]
If superview now shrinks then, if the Compression Resistance priority > 500, it'll look like this
[Click Me]
Else if Compression Resistance priority < 500, it could look like this:
[Cli..]
If it doesn't work like this then you've probably got some other constraints going on that are messing up your good work!
E.g. you could have it pinned to the superview with priority 1000. Or you could have a width priority. If so, this can be helpful:
Editor > Size to Fit Content

2017년 9월 18일 월요일

Setting Custom View Properties

1. add keyword @IBDesignable before class
2. add Keyword @IBInspectable properties

ex ) MyView.swift


@IBDesignable MyView : UIView {

    var titleLabel:UILabel?

   

    @IBInspectable var textColor : UIColor! {

        didSet {

            if self.titleLabel != nil {

                self.titleLabel.textColor = textColor

            }

        }

    }

}

2017년 8월 21일 월요일

Failable Init

class FailInit {

    var name : String?
    init?( name: String){
        if name.isEmpty {
            return nil  //available in failure init methods
        }
        self.name = name
    }

    func desc() {
        print("name is \(self.name!)")
    }

}



var f = FailInit(name:"kim")
f!.desc()
var m = FailInit(name:"")   //init failed
if m == nil {
    print("nil found")
}



/*
 name is kim
 nil found
 */

convenience vs designated init

Calling self init method can be available in convenience init method, not in designated init method
class Vehicle {
    var numberOfWheels = 0
    var name : String = ""
    init(numberOfWheels:Int){
        self.numberOfWheels = numberOfWheels
    }

    convenience init(name:String , wheels:Int){
        self.init(numberOfWheels: wheels)
        self.name = name
    }


    init(name:String , wheels:Int){        // ERROR : designated init can't call self init
        self.init(numberOfWheels: wheels)
        self.name = name
    }

    func desc() {
        print("\(name) has \(numberOfWheels)")
    }

2017년 7월 19일 수요일

GameObject Instatiated Lifecycle

GameObject Instatiated Lifecycle

When you call Instantiate on a prefab, the Awake() function is run immediately, but NOT the Start() function. The Start function is run sometime later before the first call to Update().



public class Cannon : MonoBehaviour{
    public GameObject prefabBullet;
    List<GameObject> list = new List<GameObject>();
    public void ReloadBullet(){
        GameObject bullet = Instantiate( prefabBullet );
        bullet.SetActive(false);
        list.Add(bullet);
    }

    public void Fire (){
        GameObject bullet = list[0];
        bullet.SetActive(true);
    }

}



//GameObject bullet has MyBullet component.

public class MyBullet : MonoBehaviour{

    void Awake(){
        Common.Log("MyBullet:Awake");
    }

    void Start(){
        Common.Log("MyBullet:Start");
    }

    void OnEnable(){
        Common.Log("MyBullet:OnEnable");
    }

    void OnDisable(){
        Common.Log("MyBullet:OnDisable");
    }

}



Cannon c;
c.ReloadBullet();

/*
MyBullet:Awake
MyBullet:OnEnable
MyBullet:OnDisable
 */



c.Fire();
/*
 MyBullet:OnEnable
 MyBullet:Start       // MyBullet:Start() is called before MyBullet:Update() is called
 */


2017년 7월 11일 화요일

Unity Animator



* 가급적 parameter , stateInfo 명은 같게 하자.
Animator parameter name : 
     State1,State2,State3
Animator StateInfo name : 
     ExBtnAnimatorState1, ExBtnAnimatorState2,     ExBtnAnimatorState3

   








    Animator ani;
    // Use this for initialization
    
    void Start () {
        ani = GetComponent<Animator>();
    }
    
    // Update is called once per frame
    void Update () {
        if(Input.GetKey("1")){
            if(!ani.GetCurrentAnimatorStateInfo(0).IsName("ExBtnAnimatorState1")){
                ani.SetTrigger("State1");
            } 
        }

    }






* Has Exit Time :
에니메이션이 끝날때까지 기다리고 다음 애니메이션으로 전환할지 여부 선택



2017년 6월 12일 월요일

GetComponentInChildren method can get also parent's Component

GetComponentInChildren,GetComponentsInChildren  methods can get all components in parent and childrens. So if the component that you want to get is in both parent and children, this method can get component in parent at first.


 GameObject <ParticleSystem> : Parent
     GameObject <ParticelSystem> : Child


ParticleSystem ptc = GetComponentInChildren<ParticleSystem>();
Debug.Log(ptc.name);  // "Parent"


solution:

foreach(ParticleSystem ptc in GetComponentsInChildren<ParticleSystem>())

{

     if( ptc.name == "Parent"){

       //do something by parent

     } else if (ptc.name == "Child"){

         //do something by Child

     }

}

*
 i think this method naming is wrong. many people get confused.

2017년 5월 30일 화요일

Unity PropertyDrawer ( Custom instpector)






[System.Serializable]
public struct FloatRange{

    //getter,setter방식은 FindPropertyRelative에서 못찾아내서 사용안함.
    public float value,min,max;

    public FloatRange(float pValue, float pMin, float pMax ){
        value = pValue;
        min = pMin;
        max = pMax;
    }
}


[CustomPropertyDrawer(typeof(FloatRange))]
public class FloatRangeDrawer : PropertyDrawer {
 
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label){
        label = EditorGUI.BeginProperty(position, label, property);
        Rect contentPosition = EditorGUI.PrefixLabel(position, label);
        contentPosition.width *= 0.33f;
        EditorGUI.indentLevel = 0;
        EditorGUIUtility.labelWidth = 14f;
        //value
        EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("value"), GUIContent.none);

        //min
        contentPosition.x += contentPosition.width;
        EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("min"), new GUIContent(","));
     
        //max
        contentPosition.x += contentPosition.width;
        EditorGUI.PropertyField(contentPosition, property.FindPropertyRelative("max"), new GUIContent("~"));

        EditorGUI.EndProperty();
    }
}

2017년 5월 17일 수요일

cocoapods install and delete

install pods

$ pod init
//make Podfile
$ sudo nano Podfile
$ pod install


delete pods
$ sudo gem install cocoapods-deintegrate cocoapods-clean
$ pod deintegrate
$ pod clean
$ rm Podfile

2017년 5월 15일 월요일

Subclass UIGestureRecognizer

#import <UIKit/UIKit.h>
#import <UIKit/UIGestureRecognizerSubclass.h> // required!!

@interface TouchGestureRecognizer : UIGestureRecognizer
@end


#import "TouchGestureRecognizer.h"
@implementation TouchGestureRecognizer
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];
    self.state = UIGestureRecognizerStateBegan;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];
    self.state = UIGestureRecognizerStateEnded;
}

- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent *)event{
    [super touchesMoved:touches withEvent:event];
    self.state = UIGestureRecognizerStateChanged;
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesCancelled:touches withEvent:event];
    self.state = UIGestureRecognizerStateCancelled;
}


@end

2017년 4월 17일 월요일

Unity Inspector

1. Header in Inspector

[Header("Transform")]
public Vector3 position;
public Vector3 rotation;

[Space]

public string objectName;

public int objectCount;


2. Hide In Inspector

[HideInInspector]

public int secret = 42;



3. show private in inspector

[SerializeField]

private int startHealth = 20;




2017년 3월 30일 목요일

iOS get UIColor from HexCode String


+ (UIColor *)colorWithHexCode:(NSString *)hexCode {
    NSString *arrangedCode = [hexCode stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    arrangedCode = arrangedCode.uppercaseString;
    if (arrangedCode.length < 6) {
        return [UIColor blackColor];
    }
    NSArray *deletingCharacters = @[@"0X", @"#"];
    for (NSString *deletingCharacter in deletingCharacters) {
        if ([arrangedCode hasPrefix:deletingCharacter]) {
            arrangedCode = [arrangedCode substringFromIndex:deletingCharacter.length];
            break;
        }
    }
    if (arrangedCode.length != 6) {
        return [UIColor blackColor];
    }
    NSString *redCode = [arrangedCode substringWithRange:NSMakeRange(0, 2)];
    NSString *greenCode = [arrangedCode substringWithRange:NSMakeRange(2, 2)];
    NSString *blueCode = [arrangedCode substringWithRange:NSMakeRange(4, 2)];
    unsigned int red, green, blue = 0;
    [[NSScanner scannerWithString:redCode] scanHexInt:&red];
    [[NSScanner scannerWithString:greenCode] scanHexInt:&green];
    [[NSScanner scannerWithString:blueCode] scanHexInt:&blue];
    return [UIColor colorWithRed:(red / 255.0f)
                           green:(green / 255.0f)
                            blue:(blue / 255.0f)
                           alpha:1.0f];
}

iOS UILabel attributedText NSForegroundColorAttributeName property doesn't work. its forecolor is transparent.






@interface UIStrokeLabel : UILabel
@property (nonatomic, assign) CGFloat stokeWidth;
@end



@implementation UIStrokeLabel
- (void)drawTextInRect:(CGRect)rect{
    self.attributedText = [[NSAttributedString alloc]
                           initWithString:self.text
                           attributes:@{
                                        NSStrokeWidthAttributeName: [NSNumber numberWithFloat:self.strokeWidth],
                                        NSStrokeColorAttributeName:[UIColor blueColor],
                                        NSForegroundColorAttributeName:self.textColor
                                        }
                           ];
    
    [super drawTextInRect:rect];
}
@end

self.strokeWidth must be under 0. 
if it is over 0, text fore color is transparent.

iOS update multiplier value of NSLayoutConstraint

- (instancetype) updateMultiplier:(CGFloat)multiplier {

    [NSLayoutConstraint deactivateConstraints:[NSArray arrayWithObjects:self, nil]];
    NSLayoutConstraint *newConstraint = [NSLayoutConstraint constraintWithItem:self.firstItem
                                                                     attribute:self.firstAttribute
                                                                     relatedBy:self.relation
                                                                        toItem:self.secondItem
                                                                     attribute:self.secondAttribute
                                                                    multiplier:multiplier
                                                                      constant:self.constant];

    [newConstraint setPriority:self.priority];
    newConstraint.shouldBeArchived = self.shouldBeArchived;
    newConstraint.identifier = self.identifier;
    newConstraint.active = true;


    [NSLayoutConstraint activateConstraints:[NSArray arrayWithObjects:newConstraint, nil]];
    return newConstraint;

}

/// Usage


@property(nonatomic, strong) NSLayoutConstraint contraintCenterX;

self.constraintCenterX = [self.constraintCeterX updateMultiplier:0.6];


autolayout not work in viewWillAppear but work in viewDidAppear.

autolayout only works after viewDidAppear.
so if you want it to do in viewWillAppear, call layoutIfNeeded there.



ex)



- (void) viewWillAppear {

....

    [myView layoutIfNeeded];

    // myView autolayouted!!

}

iOS Creating Custom View

Creating MyView

1. Creating MyView Class

@interface MyView : UIView

@property(nonatomic,strong) UIView* contentView;

@property(nonatomic,strong) NSBundle* bundle;

@end





#import “MyView.h”

@implementation MyView

- (instancetype)initWithCoder:(NSCoder *)aDecoder{

    self = [super initWithCoder:aDecoder];

    if( self ){

        self.bundle = [NSBundle bundleForClass:[self class]];

        if (self.subviews.count == 0) {

            self.contentView = [[self.bundle loadNibNamed:NSStringFromClass([self class]) owner:self options:nil] objectAtIndex:0];

            [self addSubview: self.contentView];

            self.contentView.frame = self.bounds;

        }

    }

    return self;

}



@end



2. Creating MyView.nib

place "MyView" in the Class field of the File's Owner.



2017년 2월 18일 토요일

Swift Inheritance, override, final

//Inheritance, override, final 


//Inheritance, override, final 

class Vehicle{
    var totalVehicles : Int = 0
    var desc:String {
        return "totalVehicles : \(totalVehicles)."
    }
}

class Bycle: Vehicle {
    override init(){
        super.init()
        self.totalVehicles = 2
    }
    override var desc : String {
        return super.desc + ", in bycle"
    }
    final func noOverrideMethod(){
        print("final keyword mean this cannot be allowed to override any more")
    }
}
class Bycle4Wheels : Bycle {
    override init(){
        super.init()
        self.totalVehicles = 4
    }

    override var desc : String {
        return super.desc + " with 4 wheels "
    }
}
var b = Bycle()
print( b.desc)
b.noOverrideMethod()
var f = Bycle4Wheels()
print( f.desc)

Swift Instance Method, Type Method,subscript

struct StructSample{
    static func typeMethod(){
        print("i am type method")
    }
    func instanceMethod(){
        print("i am instance method")
    }
}

var s = StructSample()
s.instanceMethod()
StructSample.typeMethod()

class ClassSample{
    //class keyword allow subclasses to override superclass implements
    class func typeMethod(){
        print("i am type method")
    }

    //static keyword not allow subclasses to override superclass implements 
    static func staticTypeMethod(){
        print(" static method from statcTypeMechod")
    }

    func instanceMethod(){
        print("i am instance method")
    }
}
var c = ClassSample()
c.instanceMethod()
ClassSample.typeMethod()


//static, class modifiers ?
class SomeClass {
    class var overrideType: Int {
        get {
            return 107
        }
    }
    static var type2 : Int  {
        get {
            return 1
        }
    }
}

print(SomeClass.overrideType)
print(SomeClass.type2)

//subscript
struct SubscriptSample{
    var weight : Int
    subscript(index:Int) -> Int {
        return index * weight
    }
}

var s = SubscriptSample(weight:3)
print( s[2],s[3])

2017년 2월 17일 금요일

Swift mutating

Modifying Value Types from Within Instance Methods Structures and enumerations are value types. By default, they cannot be modified from within its instance Methods However, if you want, you can opt in to "mutating" keyword. mutating The mutating keyword is added to its definition to enable it to modify its properties.


struct RectST {
    var x : Double = 0
    func minus(x dx:Int ){
       x -= dx     error: Left side of mutating operator isn't mutable: 'self' is immutable
    }
    mutating func move (x dx:Double){
        x += dx
    }
    mutating func moveSelf(x dx:Double){
        self = RectST(x:dx)
    }
}

class Rect {
    var x : Double = 0
    func move (x dx:Double){
        x += dx
    }
}

var c01 = RectST()
c01.minus(x:3)
c01.move(x:222) 

enum TriStateSwitch {
    case off,low,high
    mutating func next(){
        switch self {
            case .off:
                self = .low
            case .low:
                self = .high
            case .high:
                self = .off
                
        }
    }

}

Swift Lazy, Computed, Observers Properties

//1. Lazy Stored Properties

class DataImporter {
    var fileName = "data.txt"
}

class DataManager {
    lazy var importer = DataImporter()
    var data = [String]()
}



var m = DataManager()
m.data.append("data 1 ")
m.data.append("data 2 ")
//m.importer has not yet been created.
print( m.importer.fileName )
//m.importer has been created now.









//2. Computed Properties

struct Point {
    var x = 0.0, y = 0.0
}

struct Size {
    var width = 0.0, height = 0.0
}



struct Rect {
    var origin = Point()
    var size = Size()
    var center : Point {

        get {
            let tmpx = origin.x + size.width/2
            let tmpy = origin.y + size.height/2
            return Point(x:tmpx,y:tmpy)

        }

        // set {
        //     origin.x = newValue.x - size.width/2
        //     origin.y = newValue.y - size.height/2
        // }

     

        // renaming newCenter as newValue
        set ( newCenter ){
            origin.x = newCenter.x - size.width/2
            origin.y = newCenter.y - size.height/2
        }
    }
}



var r = Rect(origin:Point(x:10,y:10), size:Size(width:20,height:20))
print( r.center)



// 3. setter, getter

class Test {
   var _power : Double = 0.0
   var power : Double {
        get {
            return _power
        }

        set (newValue){
            _power = newValue
        }
    }
}







/* 4.Property Objservers


willSet is called just before the value is stored.
didSet is called immediately after the new value is stored.”

*/



class Sample {
    var force : Int = 0 {
        willSet(newV){
            print("\(force) -> \(newV)")
        }

        didSet {
            print("\(oldValue) -> \(force)")
        }
    }
}


var s = Sample()
print(s.force)
s.force = 12
print(s.force)

swift class and struct

Class have additional capablities that sturctures do not
 - Inheritance enables one class to inherit the characteristics of another. 
- Type casting enables you to check and interpret the type of a class instance at runtime. 
- Deinitializers enable an instance of a class to free up any resources it has assigned. 
- Reference counting allows more than one reference to a class instance. 

 Structures are always copied when they are passed around in your code, and do not use reference counting.

struct Resolution {
    var width = 0
    var height = 0
}

class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var framerate = 0.0
    var name: String?
}


var hd = Resolution(width:30,height:100)
var tmpHd = hd
tmpHd.width = 120


//sturct and enumeration are value types
print("sturct  \(hd.width) != \(tmpHd.width). copied")
var c = VideoMode()
c.resolution.width = 200
c.resolution.height = 300

var tmpC = c
tmpC.resolution.width = 120



/*
class is reference type
 identical operator : === , !==
*/

print("class \(c.resolution.width) == \(tmpC.resolution.width). reference")

if c === tmpC { 
    print ("class identical operator. equal")
}
// else if c !== tmpC






As a general guideline, consider creating a structure when one or more of these conditions apply:
- The structure’s primary purpose is to encapsulate a few relatively simple data values.
- It is reasonable to expect that the encapsulated values will be copied rather than referenced when you assign or pass around an instance of that structure.
- Any properties stored by the structure are themselves value types, which would also be expected to be copied rather than referenced.
- The structure does not need to inherit properties or behavior from another existing type. Examples of good candidates for structures include:
- The size of a geometric shape, perhaps encapsulating a width property and a height property, both of type Double.
- A way to refer to ranges within a series, perhaps encapsulating a start property and a length property, both of type Int. - A point in a 3D coordinate system, perhaps encapsulating x, y and z properties, each of type Double.”

Swift Enumerations : Raw value, Initializing, indirect


// Enumerations : Raw value

enum ASCIICharacterControl: Character {
    case tab = "\t"
    case lineFeed = "\n"
    case carriageReturn = "\r"
}

print("test\(ASCIICharacterControl.tab.rawValue)tabtab\(ASCIICharacterControl.lineFeed.rawValue)...")

enum Planet:Int {
    case sun=1,mercury,earth,mars,neptune,jupiter
}

print("\(Planet.sun),\(Planet.earth.rawValue)..")

enum CompassPoint: String {
    case east,west,south,north
}

print("\(CompassPoint.east)..\(CompassPoint.west.rawValue)")

// Enumerations : Initializing

var position = 3
if let planetTmp = Planet(rawValue: position) {
    switch planetTmp {
        case .earth:
            print("you choose \(planetTmp)")
        default:
            print("you choose other except earth:\(planetTmp)")
    }
} else {
    print("there is no planet with rawValue:\(position)")
}



//Recursive Enumerations : indirect

indirect enum ArithmethicExpression {
    case number(Int)
    case addition( ArithmethicExpression, ArithmethicExpression )
    case multiply( ArithmethicExpression, ArithmethicExpression )
}

let one = ArithmethicExpression.number(1)
let three = ArithmethicExpression.number(3)
let sum = ArithmethicExpression.addition(one,three)
let multi = ArithmethicExpression.multiply(sum,three)

func calculate(_ val: ArithmethicExpression ) -> Int {
    var ret : Int = 0
    switch val {
        case .number( let n ):
            ret = n
        case let .addition( a, b ):
            ret = calculate(a) + calculate(b)
        case let .multiply ( a, b ):
            ret = calculate(a) * calculate(b)
        default:
            print("nothing \(val)")
    }
    return ret
}
print( calculate(sum))
print( calculate(multi))

Swift Enumeration,Associated values

//1. Enumerations



enum SomeEnumeration {

}

enum CompassPoint {
    case north
    case south
    case east
    case west
}

enum Planet {
    case Sun,Mercury,Earth,Mars,Jupiter,Neptune
}

var directionToHead = CompassPoint.north
print(directionToHead)
directionToHead = .west
print(directionToHead)

switch directionToHead {
    case .north:
        print("switch: \(directionToHead)")
    case .south:
        print("switch: \(directionToHead)")
    case .east:
        print("switch: \(directionToHead)")
    case .west:
        print("switch: \(directionToHead)")
}


//2. Associated Values

enum BarCode {
    case upc(Int,Int,Int,Int)
    case qrCode(String)
}

var bCode = BarCode.upc(1,3,4,66)
print(bCode)
bCode = .qrCode("hi hello")
print(bCode)

switch bCode {
    case .upc(let leftPos,let topPos,let rightPos,let bottomPos):
        print ("upc \(leftPos), \(topPos), \(rightPos), \(bottomPos)")
    case let .qrCode(name):
        print ("hey \(name)")
}

Swift autoclosure

// 1. Closure - Autoclosure
“An autoclosure is a closure that is automatically created to wrap an expression that’s being passed as an argument to a function. It doesn’t take any arguments, and when it’s called, it returns the value of the expression that’s wrapped inside of it. This syntactic convenience lets you omit braces around a function’s parameter by writing a normal expression instead of an explicit closure.”





var customersInLine = ["james","kim","lee","richard","micheal","blondes","linda"]
let customerProvider = { customersInLine.remove(at:0) } // autoclosure : ()->String
print( customersInLine.count )
print( customerProvider() )
print( customersInLine.count )



//not autoclosure

func serve(customer: ()->String){
    print("serve:\(customer())")
}

serve(customer: { customersInLine.remove(at:0) } )
print (customersInLine.count)


//autoclosure
func serveAutoclosure(customer: @autoclosure ()->String ){
    print("serve by Autoclosure:\(customer())")
}
serveAutoclosure(customer: customersInLine.remove(at:0))
print (customersInLine.count)



// + escaping
var tempClosures : [()->String] = []
func collectClosures(itemClosure: @autoclosure @escaping ()->String){
    tempClosures.append(itemClosure)
}
collectClosures(itemClosure: customersInLine.remove(at:0))
collectClosures(itemClosure: customersInLine.remove(at:0))
for i in tempClosures {
    print("customer:\(i()), count:\(customersInLine.count)")
}


Swift closure : Capturing value, Escaping Closures

//1. Closure : Capturing value


func makeIncrement( forIncrement amount: Int) -> ()->Int {
    var sum = 0 // this is captured value
    func add () -> Int {
        sum += amount
        return sum
    }
    return add
}

let incrementBy5 = makeIncrement(forIncrement:5)
print(incrementBy5())
print(incrementBy5())
let incrementBy3 = makeIncrement(forIncrement:3)
print(incrementBy3())
print(incrementBy3())


//Closures are Reference Type
let incrementTemp = incrementBy3
print(incrementTemp())


//2. Closure : Escaping Closures
/*
A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns.
*/

var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping  () -> Void) {
    completionHandlers.append(completionHandler)    
    // closure is not called in this scope. @escaping required
    // completionHandler() // closure is called in this scope. @escaping not required
}

func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}

class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { self.x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200"
completionHandlers.first?()
print(instance.x)
// Prints "100”


Swift nested function, closure

// 1. nested function return type

func sumOrSub(enable:Bool) -> (Int,Int)->Int {
    func add(_ a: Int, _ b:Int )->Int {
        return a+b
    }

    func sub(_ a:Int , _ b:Int)->Int {
        return a - b
    }

    if(enable){
        return add
    }
    else {
        return sub
    }

}

print( sumOrSub(enable:true)(1,2))





// 2. closure

let names = ["james","charile","richard","hong","kim","lee"]
func backward(_ a:String, _ b:String)->Bool {
    return (a > b )
}
var reversed = names.sorted(by:backward)
print (reversed)

reversed = names.sorted(by: { (a:String, b:String)->Bool in return a>b })
print (reversed)

reversed = names.sorted(by: { s1,s2 in return s1>s2 })
print( reversed) 

reversed = names.sorted(by: { s1,s2 in s1>s2 })
print( reversed) 


reversed = names.sorted(by: { return $0>$1})
print( reversed)


reversed = names.sorted(by: { $0>$1})
print( reversed)

reversed = names.sorted(by: > )
print( reversed)


//trailing closure

reversed = names.sorted(){ $0>$1}
print( reversed)
reversed = names.sorted{ $0>$1}
print( reversed)
reversed = names.sorted{ ( a, b) -> Bool in return a > b }
print( reversed)

Swift multiples return, variadic parameters, in-out parameters

// 1. multiples return values

func limitArray(array: [Int])->(min:Int, max:Int){
    var tmpMin = 0,tmpMax = 0
    for t in array {
        if tmpMax < t {
            tmpMax = t
        }
        if tmpMin > t {
            tmpMin = t
        }
    }
    return (tmpMin, tmpMax)

}

let limit = limitArray( array: [2,5,1,6,7,8,11])
print( limit.min, limit.max)


// 2. Variadic parameters
func average(_ vals: Int...)->Double {
    var sum  = 0
    for val in vals {
        sum += val
    }
    return Double(sum) / Double(vals.count )
}

print( average(1,2,3,4,5) )


// 3. In-Out parameters

func swapInt(_  a: inout Int, _ b: inout Int ){
    let tmp = a
    a = b
    b = tmp
}
var a2 = 11
var b2 = 2
swapInt(&a2, &b2)
print(a2,b2)


Swift loop, guard

//2. label loop

let finalSquare = 25
var board = [Int](repeating: 0, count: finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
var square = 0
var diceRoll = 0

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!")


//3. guard

func greet(person: [String: String]) {
    guard let name = person["name"] else {
        return
    }
    print("Hello \(name)!")

}
greet(person: ["addr": "south korea, seoul"])
greet(person: ["name": "hjkim"])


// 4. checking API availability

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
}