1. 이전 포스팅 확인하기

 

https://growingsaja.tistory.com/942

 

[Objective-C] 앱 만들기 입문 - 30 : 환율 정보 수집으로 두나무 하나은행 환율 정보 기능 추가 및 환

1. 이전 포스팅 확인하기 https://growingsaja.tistory.com/932 2. 이번 목표 a. 두나무의 환율 정보 제공 api 사용, 데이터의 출처는 하나은행으로 추측됩니다. b. 환율 노출 기능 개선 (사용할 수 있을까 싶어

growingsaja.tistory.com

 

 

 

 

 

2. 이번 목표

 

  a. 2개 거래소로부터 Futures 정보 수집해서 저장 기능 구현

      Bybit, Bitget

 

  b. 주의할 점

      Futures의 경우 Spot에 비해 거래소별로 제공하는 api return data의 형태가 다를 수 있습니다. return data type들을 유사하나 사용방법이나 symbol 표현 방식이 달라 예외처리가 필요합니다.

 

 

 

 

 

3. 가격 관련 정보 수집해 데이터 들고있는 기능 소스코스 확인 및 수정

 

Spot 말고 Futures도 추가

 

// vim AllPriceLiveData.h

@interface AllPriceLiveData : NSObject

// ****** 현재 가격 정보 저장하는 데이터 ****** //
// 최신 Spot 가격 정보 저장용 데이터
@property (readwrite, strong, nonatomic) NSMutableDictionary *recentSpotTicker;
// 최신 Futures 가격 정보 저장용 데이터
@property (readwrite, strong, nonatomic) NSMutableDictionary *recentFuturesTicker;

+(instancetype) sharedInstance;

@end

 

// vim AllPriceLiveData.m

#import <Foundation/Foundation.h>
#import "AllPriceLiveData.h"
#import "DefaultLoader.h"

@implementation AllPriceLiveData

+(instancetype)sharedInstance {
    static AllPriceLiveData *sharedInstance = nil;
    static dispatch_once_t oneToken;
    dispatch_once(&oneToken, ^{
        sharedInstance = [[self alloc] init];
        // 초기값 세팅 (안해주면 for문 돌면서 해당 dictionary에 데이터가 들어가지 않음)
        sharedInstance.recentSpotTicker = [@{} mutableCopy];
        sharedInstance.recentFuturesTicker = [@{} mutableCopy];
        // exchange Info 활용해서 데이터 초기 세팅하기 - Spot
        NSArray *exchangeListSpot = [DefaultLoader sharedInstance].exchangeListSpot;
        for (NSString *exchangeName in exchangeListSpot) {
            sharedInstance.recentSpotTicker[exchangeName] = [@{} mutableCopy];
        }
        // exchange Info 활용해서 데이터 초기 세팅하기 - Futures
        NSArray *exchangeListFutures = [DefaultLoader sharedInstance].exchangeListFutures;
        NSLog(@"exchangeListFutures : %@", exchangeListFutures);
        for (NSString *exchangeName in exchangeListFutures) {
            sharedInstance.recentFuturesTicker[exchangeName] = [@{} mutableCopy];
        }
        NSLog(@"shared exchangeListFutures : %@", sharedInstance.recentFuturesTicker);
    });
    return sharedInstance;
}

@end

 

 

 

 

 

4. Bybit 현물 정보 수집 기능 확인

 

// vim SpotBybit.h

@interface SpotBybit : NSObject

// asset, payment currency 기준으로 현재 실시간 정보 얻기
@property (readwrite, strong, nonatomic) NSMutableDictionary *dataFromAsset;

// payment currency 정보
@property (readwrite, strong, nonatomic) NSMutableDictionary *paymentCurrencyInfo;

+(instancetype)sharedInstance;
-(void) fetchDataWithCompletion;

@end

 

// vim SpotBybit.m

#import <Foundation/Foundation.h>
#import "SpotBybit.h"
// 주요 데이터 get
#import "DefaultLoader.h"
// api 연결
#import "APIManager.h"

@implementation SpotBybit

+(instancetype)sharedInstance {
    static SpotBybit *sharedInstance = nil;
    static dispatch_once_t oneToken;
    dispatch_once(&oneToken, ^{
        sharedInstance = [[self alloc] init];
        // 가격 정보 초기 설정
        sharedInstance.dataFromAsset = [@{} mutableCopy];
        // 취급 화폐 초기 설정
        sharedInstance.paymentCurrencyInfo = [@{} mutableCopy];
        // payment currency 데이터 참조해서 symbol 찢기 용도 데이터셋 선언
        [sharedInstance getOnlyPaymentCurrencyInfo];
    });
    return sharedInstance;
}

-(void) fetchDataWithCompletion {
    // **************************************** [Start] default 데이터 가공 **************************************** //
    // bybit 관련 default 데이터 불러오기
    NSDictionary *bybit = [DefaultLoader sharedInstance].exchangeInfo[@"Bybit"];
    // **************************************** [Start] api 콜 준비 **************************************** //
    APIManager* tryApiCall = [APIManager sharedInstance];
    // **************************************** [Start] Bybit 현재 호가, 변동률 등 주요 데이터 가져오기 **************************************** //
    NSString *apiURL = [bybit[@"information"][@"baseUrlList"][0] stringByAppendingString:bybit[@"information"][@"publicApi"][@"ticker"]];
    apiURL = [apiURL stringByAppendingString:@"?category=spot"];
    [tryApiCall fetchDataFromAPI:apiURL withCompletionHandler:^(NSDictionary *jsonResponse, NSError *error) {
        if (error) {
            NSLog(@"[Error] Bybit Spot Api : %@", error.localizedDescription);
        } else {
            // 여기에서 jsonResponse를 가공 한 후 앱에서 사용하실 수 있습니다.
            if ([jsonResponse[@"retCode"] isEqual:@0]) {
                // ****** 정상 성공시 ****** //
                // 에러가 발생하지 않은 경우 result라는 키값을 가지며 그 안에 category 및 list로 상품별 정보를 가집니다. 추가로 time, retExtInfo라는 키값을 포함해 총 4개의 데이터를 return합니다. (time은 unix timestamp입니다.)
                // result 안의 value만 추출
                NSArray* resultOfApi = jsonResponse[@"result"][@"list"];
                // api로 받은 데이터 깔끔한 dictionary로 가공하기
                for (int i=0; i<resultOfApi.count; i++) {
                    /* #################### dataFromSymbol #################### */
                    // ****** api의 데이터들 수집한거 필요시 가공해서 저장하기 ****** //
                    NSString *symbol = resultOfApi[i][@"symbol"]; // 심볼
                    NSString *price = resultOfApi[i][@"lastPrice"]; // 가격
                    // 변동률은 데이터를 다른 거래소 정보와 함께 노출시 통일성있게 하기 위해 부분 가공이 진행됩니다.
                    NSString *changePricePercent24 = [NSString stringWithFormat:@"%.2f", [resultOfApi[i][@"price24hPcnt"] floatValue] * 100]; // 근24시간 가격 변동률
                    if (![changePricePercent24 hasPrefix:@"-"]) {
                        // 음수가 아닌 경우, +로 기호 맨앞에 붙여주기
                        changePricePercent24 = [@"+" stringByAppendingString:changePricePercent24];
                    }
                    NSString *volume24 = resultOfApi[i][@"volume24h"]; // 근24시간 거래량
                    NSString *turnover24 = resultOfApi[i][@"turnover24h"]; // 근24시간 거래대금
                    /* #################### dataFromAsset #################### */
                    // dataFromAsset
                    NSString *asset;
                    NSString *paymentCurrency;
                    // 사용된 payment currency 찾고 symbol을 찢기
                    for (NSString *eachPaymentCurrency in self.paymentCurrencyInfo[@"spot"]) {
                        // 뒤에 payment currency 매치되는거 찾은 경우 분리 진행
                        if ([symbol hasSuffix:eachPaymentCurrency]) {
                            asset = [[symbol componentsSeparatedByString:eachPaymentCurrency] objectAtIndex:0];
                            paymentCurrency = eachPaymentCurrency;
                        }
                    }
                    // ****** 데이터 저장 진행 ****** //
                    if (asset && paymentCurrency) {
                        // symbol을 asset과 payment 분리에 성공한 경우, 정상적인 데이터 수집 절차가 진행됩니다.
                        if ( ! [self.dataFromAsset objectForKey:asset]) {
                            // asset 키값이 없는 경우, 만들어줍니다.
                            self.dataFromAsset[asset] = [@{} mutableCopy];
                        }
                        // dataFromAsset 데이터셋 생성
                        self.dataFromAsset[asset][paymentCurrency] = [@{} mutableCopy];
                        self.dataFromAsset[asset][paymentCurrency][@"price"] = price; // 가격
                        self.dataFromAsset[asset][paymentCurrency][@"changePricePercent24"] = changePricePercent24; // 근24시간 가격 변동률
                        self.dataFromAsset[asset][paymentCurrency][@"turnover24"] = turnover24; // 근24시간 거래대금
                        self.dataFromAsset[asset][paymentCurrency][@"volume24"] = volume24; // 근24시간 거래량
                    } else {
                        // 취급하지 않는 payment currency가 발견된 경우 = default.json에서 개발자가 인지하지 못한 payment currency가 발견된 경우 알림
                        NSLog(@"[WARN] Bybit Spot list doesn't have this payment currency. : %@", symbol);
                    }
                }
            } else {
                // ****** 비정상으로 실패시 ****** //
                // 에러가 발생한 경우 retCode는 0이 아니며, retMsg에 관련 상세 내용이 있습니다.
                NSLog(@"[WARN] Bybit Spot Return Data => Code : %@, Message : %@", jsonResponse[@"retCode"], jsonResponse[@"retMsg"]);
            }
        }
    }];
}

// _paymentCurrencyInfo : spot, futures 각각에서 취급하는 paymentCurrencyList를 보유하게 됩니다. 해당 정보를 토대로, symbol 데이터를 활용해 asset과 paymentCurrency를 분리합니다.
-(void) getOnlyPaymentCurrencyInfo {
    // bybit 관련 default 데이터 불러오기
    NSDictionary *bybit = [DefaultLoader sharedInstance].exchangeInfo[@"Bybit"];
    NSArray *categoryList = @[@"spot", @"futures"];
    // 데이터 정리하기
    for (NSString *category in categoryList) {
        _paymentCurrencyInfo[category] = [@[] mutableCopy];
        for (NSString *group in [bybit[category] allKeys]) {
            if ([bybit[category][group][@"category"] isEqual:category]) {
                // spot
                [_paymentCurrencyInfo[category] addObjectsFromArray:bybit[category][group][@"paymentCurrencyList"]];
            } else if ([bybit[category][group][@"category"] isEqual:@"inverse"]) {
                // usd
                [_paymentCurrencyInfo[category] addObjectsFromArray:bybit[category][@"coinMargin"][@"paymentCurrencyList"]];
            } else if ([bybit[category][group][@"category"] isEqual:@"linear"]) {
                // usdt
                [_paymentCurrencyInfo[category] addObjectsFromArray:bybit[category][@"stableMargin"][@"paymentCurrencyList"]];
            } else {
                NSLog(@"[WARN] Bybit Spot payment currency not match : Skip... -> bybit[category][group][@\"category\"] : %@", bybit[category][group][@"category"]);
            }
        }
    }
}

@end

 

 

 

 

 

5. bybit api 관련 정보 추가

 

// vim default.json



// ...



                }
            }
        },
        "Bybit": {
            "isActive": {
                "spot": true,
                "futures": true
            },
            "information": {
                "image": "exchangeBybit.jpeg",
                "keyList": [],
                "baseUrlList": [
                    "https://api.bybit.com",
                    "https://api.bytick.com"
                ],
                "publicApi": {
                    "ticker": "/v5/market/tickers",
                    "orderbook": ""
                }
            },
            "spot": {
                "stable": {
                    "category": "spot",
                    "paymentCurrencyList": ["USDT", "USDC", "DAI"]
                },
                "bitcoin": {
                    "category": "spot",
                    "paymentCurrencyList": ["BTC"]
                },
                "alt": {
                    "category": "spot",
                    "paymentCurrencyList": ["BRZ"]
                },
                "fiat": {
                    "category": "spot",
                    "paymentCurrencyList": ["EUR"]
                }
            },
            "futures": {
                "stableMargin" : {
                    "category": "linear",
                    "paymentCurrencyList": ["USDT", "USDC"]
                },
                "coinMargin": {
                    "category": "inverse",
                    "paymentCurrencyList": ["USD"]
                }
            }
        },
        "Bitget": {
            "isActive": {



// ...

 

 

 

 

 

6. Bybit 선물 정보 수집 기능 개발

 

// vim FuturesBybit.h

@interface FuturesBybit : NSObject

// asset, payment currency 기준으로 현재 실시간 정보 얻기
@property (readwrite, strong, nonatomic) NSMutableDictionary *dataFromAsset;

// payment currency 정보
@property (readwrite, strong, nonatomic) NSMutableDictionary *paymentCurrencyInfo;

+(instancetype)sharedInstance;
-(void) fetchDataWithCompletion;

@end

 

// vim FuturesBybit.m

#import <Foundation/Foundation.h>
#import "FuturesBybit.h"
// 주요 데이터 get
#import "DefaultLoader.h"
// api 연결
#import "APIManager.h"

@implementation FuturesBybit

+(instancetype)sharedInstance {
    static FuturesBybit *sharedInstance = nil;
    static dispatch_once_t oneToken;
    dispatch_once(&oneToken, ^{
        sharedInstance = [[self alloc] init];
        // 가격 정보 초기 설정
        sharedInstance.dataFromAsset = [@{} mutableCopy];
        // 취급 화폐 초기 설정
        sharedInstance.paymentCurrencyInfo = [@{} mutableCopy];
        // payment currency 데이터 참조해서 symbol 찢기 용도 데이터셋 선언
        [sharedInstance getOnlyPaymentCurrencyInfo];
    });
    return sharedInstance;
}

-(void) fetchDataWithCompletion {
    // **************************************** [Start] default 데이터 가공 **************************************** //
    // bybit 관련 default 데이터 불러오기
    NSDictionary *bybit = [DefaultLoader sharedInstance].exchangeInfo[@"Bybit"];
    // **************************************** [Start] api 콜 준비 **************************************** //
    APIManager* tryApiCall = [APIManager sharedInstance];
    // **************************************** [Start] Bybit 현재 호가, 변동률 등 주요 데이터 가져오기 **************************************** //
    for (NSString *bybit_category in @[@"linear", @"inverse"]) {
        NSString *apiURL = [bybit[@"information"][@"baseUrlList"][0] stringByAppendingString:bybit[@"information"][@"publicApi"][@"ticker"]];
        apiURL = [apiURL stringByAppendingString:@"?category="];
        apiURL = [apiURL stringByAppendingString:bybit_category];
        [tryApiCall fetchDataFromAPI:apiURL withCompletionHandler:^(NSDictionary *jsonResponse, NSError *error) {
            if (error) {
                NSLog(@"[Error] Bybit Futures Api : %@", error.localizedDescription);
            } else {
                // 여기에서 jsonResponse를 가공 한 후 앱에서 사용하실 수 있습니다.
                if ([jsonResponse[@"retCode"] isEqual:@0]) {
                    // ****** 정상 성공시 ****** //
                    // 에러가 발생하지 않은 경우 result라는 키값을 가지며 그 안에 category 및 list로 상품별 정보를 가집니다. 추가로 time, retExtInfo라는 키값을 포함해 총 4개의 데이터를 return합니다. (time은 unix timestamp입니다.)
                    // result 안의 value만 추출
                    NSArray* resultOfApi = jsonResponse[@"result"][@"list"];
                    // api로 받은 데이터 깔끔한 dictionary로 가공하기
                    for (int i=0; i<resultOfApi.count; i++) {
                        /* #################### dataFromSymbol #################### */
                        // ****** api의 데이터들 수집한거 필요시 가공해서 저장하기 ****** //
                        NSString *symbol = resultOfApi[i][@"symbol"]; // 심볼
                        NSString *price = resultOfApi[i][@"lastPrice"]; // 가격
                        // 변동률은 데이터를 다른 거래소 정보와 함께 노출시 통일성있게 하기 위해 부분 가공이 진행됩니다.
                        NSString *changePricePercent24 = [NSString stringWithFormat:@"%.2f", [resultOfApi[i][@"price24hPcnt"] floatValue] * 100]; // 근24시간 가격 변동률
                        if (![changePricePercent24 hasPrefix:@"-"]) {
                            // 음수가 아닌 경우, +로 기호 맨앞에 붙여주기
                            changePricePercent24 = [@"+" stringByAppendingString:changePricePercent24];
                        }
                        NSString *volume24 = resultOfApi[i][@"volume24h"]; // 근24시간 거래량
                        NSString *turnover24 = resultOfApi[i][@"turnover24h"]; // 근24시간 거래대금
                        /* #################### dataFromAsset #################### */
                        // dataFromAsset
                        NSString *asset;
                        NSString *paymentCurrency;
                        
                        // 사용된 payment currency 찾고 symbol을 찢기
                        if ([symbol hasSuffix:@"PERP"]) {
                            asset = [[symbol componentsSeparatedByString:@"PERP"] objectAtIndex:0];
                            // Bybit linear 유기한 삭제 - PERP는 모두 USDC로 표기합니다.
                            paymentCurrency = @"USDC";
                        } else {
                            for (NSString *eachPaymentCurrency in self.paymentCurrencyInfo[@"futures"]) {
                                // 뒤에 payment currency 매치되는거 찾은 경우 분리 진행
                                if ([symbol hasSuffix:eachPaymentCurrency]) {
                                    asset = [[symbol componentsSeparatedByString:eachPaymentCurrency] objectAtIndex:0];
                                    paymentCurrency = eachPaymentCurrency;
                                }
                                // 여기에서 else를 안쓰는 이유는, 위 for문이 돌면서 1개만이라도 걸리면 일단 고려한 payment currency인 것이기 때문에 아래 if asset&paymentCurrency에서 체크한다.
                            }
                        }
                        // ****** 데이터 저장 진행 ****** //
                        if (asset && paymentCurrency) {
                            // symbol을 asset과 payment 분리에 성공한 경우, 정상적인 데이터 수집 절차가 진행됩니다.
                            if ( ! [self.dataFromAsset objectForKey:asset]) {
                                // asset 키값이 없는 경우, 만들어줍니다.
                                self.dataFromAsset[asset] = [@{} mutableCopy];
                            }
                            // dataFromAsset 데이터셋 생성
                            self.dataFromAsset[asset][paymentCurrency] = [@{} mutableCopy];
                            self.dataFromAsset[asset][paymentCurrency][@"price"] = price; // 가격
                            self.dataFromAsset[asset][paymentCurrency][@"changePricePercent24"] = changePricePercent24; // 근24시간 가격 변동률
                            self.dataFromAsset[asset][paymentCurrency][@"turnover24"] = turnover24; // 근24시간 거래대금
                            self.dataFromAsset[asset][paymentCurrency][@"volume24"] = volume24; // 근24시간 거래량
                        } else {
                            // Bybit inverse의 경우 U23 또는 Z23이 뒤에 붙으면 유기한 선물 : U23 9월 29일, Z23 12월 29일
                            // Bybit linear의 경우 PERP가 뒤에 붙으면 USDC 단위의 futures이므로 예외처리를 해주고, 유기한 선물도 있기에 유기한 선물은 제외하기
                            if ([symbol hasSuffix:@"U23"] || [symbol hasSuffix:@"Z23"]) {
                                // Bybit inverse 유기한 삭제 - 마감일자 관련 정보 있는 경우 취급 데이터에서 제거
                                // pass
                            } else if ([symbol containsString:@"-"]) {
                                // Bybit linear 유기한 삭제 - 1차 필터링
                                if ([symbol containsString:@"AUG2"] || [symbol containsString:@"SEP2"] || [symbol containsString:@"OCT2"] || [symbol containsString:@"DEC2"] || [symbol containsString:@"MAR2"]) {
                                    // Bybit linear 유기한 삭제 - 마감날짜정보가 있을 것이기에 있는지 확인해서, 해당 건은 취급 데이터에서 제거
                                    // pass
                                } else {
                                    // 유기한 선물 중 취급하지 않는 payment currency가 발견된 경우 = 여기 조건문 소스코드에서 예외처리에 추가해줘야함
                                    NSLog(@"[WARN] Bybit Futures Term-Contract list doesn't have this payment currency. : %@", symbol);
                                }
                            } else {
                                // 취급하지 않는 payment currency가 발견된 경우 = default.json에서 개발자가 인지하지 못한 payment currency가 발견된 경우 알림
                                NSLog(@"[WARN] Bybit Futures list doesn't have this payment currency. : %@", symbol);
                            }
                        }
                    }
                } else {
                    // ****** 비정상으로 실패시 ****** //
                    // 에러가 발생한 경우 retCode는 0이 아니며, retMsg에 관련 상세 내용이 있습니다.
                    NSLog(@"[WARN] Bybit Return Data => Code : %@, Message : %@", jsonResponse[@"retCode"], jsonResponse[@"retMsg"]);
                }
            }
        }];
    }
}

// _paymentCurrencyInfo : spot, futures 각각에서 취급하는 paymentCurrencyList를 보유하게 됩니다. 해당 정보를 토대로, symbol 데이터를 활용해 asset과 paymentCurrency를 분리합니다.
-(void) getOnlyPaymentCurrencyInfo {
    // bybit 관련 default 데이터 불러오기
    NSDictionary *bybit = [DefaultLoader sharedInstance].exchangeInfo[@"Bybit"];
    NSArray *categoryList = @[@"spot", @"futures"];
    // 데이터 정리하기
    for (NSString *category in categoryList) {
        _paymentCurrencyInfo[category] = [@[] mutableCopy];
        for (NSString *group in [bybit[category] allKeys]) {
            if ([bybit[category][group][@"category"] isEqual:category]) {
                // spot
                [_paymentCurrencyInfo[category] addObjectsFromArray:bybit[category][group][@"paymentCurrencyList"]];
            } else if ([bybit[category][group][@"category"] isEqual:@"inverse"]) {
                // usd
                [_paymentCurrencyInfo[category] addObjectsFromArray:bybit[category][@"coinMargin"][@"paymentCurrencyList"]];
            } else if ([bybit[category][group][@"category"] isEqual:@"linear"]) {
                // usdt
                [_paymentCurrencyInfo[category] addObjectsFromArray:bybit[category][@"stableMargin"][@"paymentCurrencyList"]];
            } else {
                NSLog(@"[WARN] Bybit Futures payment currency not match : Skip... -> bybit[category][group][@\"category\"] : %@", bybit[category][group][@"category"]);
            }
        }
    }
}

@end

 

 

 

 

 

7. AppDelegate에 앱 실행시 계속 작동되도록 데이터 업데이트 주기적으로 진행하는 소스코드 추가

 

// vim AppDelegate.h

#import <UIKit/UIKit.h>

// MARK: - [클래스 설명]
/*
// -----------------------------------------
1. 애플리케이션 딜리게이트 (선언부)
2. 전역변수 , 메소드 , 인스턴스변수 (클래스 생성자) 선언
// -----------------------------------------
*/



// -----------------------------------------
@interface AppDelegate : UIResponder <UIApplicationDelegate>
// -----------------------------------------

/* #################### 데이터 세팅 #################### */
// default.json의 exchangeInfo 저장
@property (strong, nonatomic) NSArray *exchangeListSpot;
@property (strong, nonatomic) NSArray *exchangeListFutures;

// MARK: [전역 변수 및 메소드 선언 부분]
/* #################### 메소드 #################### */
// 환율
-(void) updateRecentRatesData;
// 거래소별로 api call을 통한 데이터 업데이트 주기가 다르게 설정되어 분리
-(void) updateSpotDataBinance;
-(void) updateSpotDataBybit;
-(void) updateSpotDataBitget;
-(void) updateSpotDataOkx;
-(void) updateSpotDataKraken;

-(void) updateFuturesDataBybit;



// -----------------------------------------
@end
// -----------------------------------------

 

// vim AppDelegate.m

#import "AppDelegate.h"

// 커스텀 셋 값 활용
#import "CustomizeSetting.h"
// price 정보 저장
#import "AllPriceLiveData.h"
// 환율 서비스
#import "ServiceRecentRates.h"
// default
#import "DefaultLoader.h"
// 거래소 api
#import "SpotBybit.h"
#import "SpotBinance.h"
#import "SpotBitget.h"
#import "SpotOkx.h"
#import "SpotKraken.h"
#import "FuturesBybit.h"



// MARK: - [헤더 [선언부] 호출]
@interface AppDelegate ()
@end
@implementation AppDelegate



// MARK: - [클래스 설명]
/*
// -----------------------------------------
1. 애플리케이션 딜리게이트 (구현부)
2. ios 13 이상 사용 : API_AVAILABLE(ios(13.0))
// -----------------------------------------
*/



// MARK: - [앱 프로세스 완료 및 앱 실행 실시]
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions API_AVAILABLE(ios(13.0)){
    // 설명 :: 앱 프로세스 완료 및 앱 실행 실시
    NSLog(@"[AppDelegate >> didFinishLaunchingWithOptions]");
    
    // **************************************** [Start] active되어 enable된 exchange 정보 가져오기 **************************************** //
    // default.json의 필요한 exchange 기본 정보 데이터 가져오기
    DefaultLoader *exchangeInfo = [DefaultLoader sharedInstance];
    _exchangeListSpot = exchangeInfo.exchangeListSpot;
    _exchangeListFutures = exchangeInfo.exchangeListFutures;
    
    // **************************************** [Start] Spot 데이터 지속 업데이트 진행 로직 실행 **************************************** //
    
    /* #################### 최근 환율 정보 업데이트 #################### */
    // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
    [NSTimer scheduledTimerWithTimeInterval:1
                                     target:self
                                   selector:@selector(updateRecentRatesData)
                                   userInfo:nil
                                    repeats:YES];
    
    if ([_exchangeListSpot containsObject:@"Binance"]) {
        /* #################### Binance 바이낸스 #################### */
        // ****** api tickers 데이터 가져오기 ****** //
        // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
        [NSTimer scheduledTimerWithTimeInterval:API_CALL_TERM_BINANCE
                                         target:self
                                       selector:@selector(updateSpotDataBinance)
                                       userInfo:nil
                                        repeats:YES];
    }
    /* #################### Bybit 바이비트 #################### */
    if ([_exchangeListSpot containsObject:@"Bybit"]) {
        // ****** api tickers 데이터 가져오기 ****** //
        // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
        [NSTimer scheduledTimerWithTimeInterval:API_CALL_TERM_REST
                                         target:self
                                       selector:@selector(updateSpotDataBybit)
                                       userInfo:nil
                                        repeats:YES];
    }
    /* #################### Bitget 비트겟 #################### */
    if ([_exchangeListSpot containsObject:@"Bitget"]) {
        // ****** api tickers 데이터 가져오기 ****** //
        [NSTimer scheduledTimerWithTimeInterval:API_CALL_TERM_REST
                                         target:self
                                       selector:@selector(updateSpotDataBitget)
                                       userInfo:nil
                                        repeats:YES];
    }
    /* #################### Okx 오케이엑스 #################### */
    if ([_exchangeListSpot containsObject:@"Okx"]) {
        // ****** api tickers 데이터 가져오기 ****** //
        // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
        [NSTimer scheduledTimerWithTimeInterval:API_CALL_TERM_REST
                                         target:self
                                       selector:@selector(updateSpotDataOkx)
                                       userInfo:nil
                                        repeats:YES];
    }
    /* #################### Kraken 크라켄 #################### */
    if ([_exchangeListSpot containsObject:@"Kraken"]) {
        // ** 2023-07-24 Kraken 미사용으로 변경 (because 최근 24시간 가격 변동률 정보 추출 불가) ** //
        // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
        [NSTimer scheduledTimerWithTimeInterval:API_CALL_TERM_REST
                                         target:self
                                       selector:@selector(updateSpotDataKraken)
                                       userInfo:nil
                                        repeats:YES];
    }
    
    // **************************************** [Start] Futures 데이터 지속 업데이트 진행 로직 실행 **************************************** //
    
    /* #################### 최근 환율 정보 업데이트 #################### */
    // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
    [NSTimer scheduledTimerWithTimeInterval:1
                                     target:self
                                   selector:@selector(updateRecentRatesData)
                                   userInfo:nil
                                    repeats:YES];
    
    /* #################### Bybit 바이비트 #################### */
    if ([_exchangeListFutures containsObject:@"Bybit"]) {
        // ****** api tickers 데이터 가져오기 ****** //
        // NSTimer 생성 및 메서드 호출 설정 - 매 특정시간마다 호출
        [NSTimer scheduledTimerWithTimeInterval:API_CALL_TERM_REST
                                         target:self
                                       selector:@selector(updateFuturesDataBybit)
                                       userInfo:nil
                                        repeats:YES];
    }
    
    return YES;
}



// MARK: - [Scene 만들기 위한 구성 객체 반환 : 스토리보드 , info]
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options API_AVAILABLE(ios(13.0)){
    // 설명 :: Scene 만들기 위한 구성 객체 반환 : 스토리보드 , info
    NSLog(@"[AppDelegate >> configurationForConnecting]");
    return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}



// MARK: - [Scene 구성 객체 해제 실시]
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions API_AVAILABLE(ios(13.0)){
    // 설명 :: Scene 구성 객체 해제 실시
    NSLog(@"[AppDelegate >> didDiscardSceneSessions]");
}



// MARK: - [애플리케이션 사용자가 작업 태스크 날린 이벤트 감지]
- (void)applicationWillTerminate:(UIApplication *)application {
    // 설명 :: 애플리케이션 사용자가 작업 태스크 날린 이벤트 감지
    NSLog(@"[AppDelegate >> applicationWillTerminate]");
}




// **************************************** [Start] Spot 데이터 지속 업데이트 진행 로직 **************************************** //

/* #################### 환율 정보 업데이트 기본 시도 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateRecentRatesData {
    // ****** USDKRW 환율 정보 업데이트 ****** //
    ServiceRecentRates *ratesInfo = [ServiceRecentRates sharedInstance];
    [ratesInfo fetchData];
}

/* #################### Binance 바이낸스 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateSpotDataBinance {
    AllPriceLiveData *allTicker = [AllPriceLiveData sharedInstance];
    // api로 받은 데이터 깔끔한 dictionary로 넣어주기
    SpotBinance *mainData = [SpotBinance sharedInstance];
    [mainData fetchDataWithCompletion];
    allTicker.recentSpotTicker[@"Binance"] = mainData.dataFromAsset;
}

/* #################### Bybit 바이비트 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateSpotDataBybit {
    AllPriceLiveData *allTicker = [AllPriceLiveData sharedInstance];
    // api로 받은 데이터 깔끔한 dictionary로 넣어주기
    SpotBybit *mainData = [SpotBybit sharedInstance];
    [mainData fetchDataWithCompletion];
    allTicker.recentSpotTicker[@"Bybit"] = mainData.dataFromAsset;
}

/* #################### Bitget 비트겟 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateSpotDataBitget {
    AllPriceLiveData *allTicker = [AllPriceLiveData sharedInstance];
    // api로 받은 데이터 깔끔한 dictionary로 넣어주기
    SpotBitget *mainData = [SpotBitget sharedInstance];
    [mainData fetchDataWithCompletion];
    allTicker.recentSpotTicker[@"Bitget"] = mainData.dataFromAsset;
}

/* #################### Okx 오케이엑스 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateSpotDataOkx {
    AllPriceLiveData *allTicker = [AllPriceLiveData sharedInstance];
    // api로 받은 데이터 깔끔한 dictionary로 넣어주기
    SpotOkx *mainData = [SpotOkx sharedInstance];
    [mainData fetchDataWithCompletion];
    allTicker.recentSpotTicker[@"Okx"] = mainData.dataFromAsset;
}

// ** 2023-07-24 Kraken 미사용으로 변경 (because 최근 24시간 가격 변동률 정보 추출 불가) ** //
/* #################### Kraken 크라켄 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateSpotDataKraken {
    AllPriceLiveData *allTicker = [AllPriceLiveData sharedInstance];
    // api로 받은 데이터 깔끔한 dictionary로 가공하기
    SpotKraken *mainData = [SpotKraken sharedInstance];
    [mainData fetchDataWithCompletion];
    allTicker.recentSpotTicker[@"Kraken"] = mainData.dataFromAsset;
}

// **************************************** [End] Spot 데이터 지속 업데이트 진행 로직 **************************************** //


// **************************************** [Start] Futures 데이터 지속 업데이트 진행 로직 **************************************** //

/* #################### Bybit 바이비트 #################### */
// ****** api tickers 데이터 가져오기 ****** //
- (void)updateFuturesDataBybit {
    AllPriceLiveData *allTicker = [AllPriceLiveData sharedInstance];
    // api로 받은 데이터 깔끔한 dictionary로 넣어주기
    FuturesBybit *mainData = [FuturesBybit sharedInstance];
    [mainData fetchDataWithCompletion];
    allTicker.recentFuturesTicker[@"Bybit"] = mainData.dataFromAsset;
}

// **************************************** [End] Futures 데이터 지속 업데이트 진행 로직 **************************************** //


// -----------------------------------------
@end
// -----------------------------------------

 

 

 

 

 

 

 

 

+ Recent posts