Objective-C 應用內多語言切換

1. 多語言切換範例程式碼

GitHub:

https://github.com/f40706/change_language_1/tree/main

2. 範例程式碼結果圖

範例程式碼中英文翻譯表

英文

“PressedEnglish" = “Pressed English";
“PressedChinese" = “Pressed Chinese";

中文

“PressedEnglish" = “點擊英文";
“PressedChinese" = “點擊中文";

2. 新增多語言方法

實際功能,可以下載GitHub範例

新增想要的語言
範例使用中文
這個英文是固定的喔
選擇使用的語言
將要使用的打勾

這樣就新增完成囉

3. 程式碼

核心程式碼

-(void) initLanguage: (NSString*) selectLanguage {
    NSString *localeLanguageCode = [[[NSBundle mainBundle] preferredLocalizations] firstObject];
    NSLog(@"localeLanguageCode-> %@",localeLanguageCode);
    
    if([selectLanguage  isEqual: @"en"]) {
        NSString *path = [[NSBundle mainBundle]pathForResource:@"en" ofType:@"lproj"];
        bundle_language = [NSBundle bundleWithPath:path];
    } else if([selectLanguage  isEqual: @"zh"]) {
        NSString *path = [[NSBundle mainBundle]pathForResource:@"zh-Hant" ofType:@"lproj"];
        bundle_language = [NSBundle bundleWithPath:path];
    }
}

-(NSString*) getStringForKey:(NSString*)key withTable:(NSString*)table {
    NSString *string = @"";
    if(bundle_language) {
        string = NSLocalizedStringFromTableInBundle(key, table, bundle_language, @"");
        return string;
    }
    string = NSLocalizedStringFromTable(key, table, @"");
    return string;
}

呼叫方式

- (IBAction)onEnglishPressed:(UIButton *)sender {
    
    [_context_label setText:[_delegate getStringForKey:@"PressedEnglish" withTable:@""]];
}

- (IBAction)onChinesePressed:(UIButton *)sender {
    [_context_label setText:[_delegate getStringForKey:@"PressedChinese" withTable:@""]];
}

- (IBAction)onLanguageChangePressed:(UIButton *)sender {
    if(_curLanguage == 1) {
        [_delegate initLanguage:@"en"];
        _curLanguage = 0;
        [_curLanguageBtn setTitle:@"當前語言:英文" forState:UIControlStateNormal];
    } else {
        [_delegate initLanguage:@"zh"];
        _curLanguage = 1;
        [_curLanguageBtn setTitle:@"當前語言:中文" forState:UIControlStateNormal];
    }
}

- (void)viewDidLoad {
    [super viewDidLoad];
    _delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    _curLanguage = 0;
    [_delegate initLanguage:@"en"];
}


Objective-C


訂閱Codeilin的旅程,若有最新消息會通知。

廣告

Objective-C 延遲與取消呼叫Function

1. 呼叫與延遲方法如下

GitHub:

https://github.com/f40706/delay_and_call_method

2. 程式碼

按下onDelayMethodPressed,10秒後會呼叫execute Function

按下onCancelMethodPressed,會"取消"延遲呼叫的execute Function

2022-03-22 22:37:18.903931+0800 delay_and_call_method[3968:102311] delay call
2022-03-22 22:37:28.905523+0800 delay_and_call_method[3968:102311] execute
2022-03-22 22:37:34.219536+0800 delay_and_call_method[3968:102311] delay call
2022-03-22 22:37:35.618120+0800 delay_and_call_method[3968:102311] cancel execute
2022-03-22 22:37:56.714777+0800 delay_and_call_method[3968:102311] delay call
2022-03-22 22:37:58.981749+0800 delay_and_call_method[3968:102311] cancel execute
2022-03-22 22:38:24.482147+0800 delay_and_call_method[3968:102311] delay call
2022-03-22 22:38:34.483330+0800 delay_and_call_method[3968:102311] execute

實際功能,可以下載GitHub範例

- (IBAction)onDelayMethodPressed:(UIButton *)sender {
    [self delayMethod:10];
}

- (IBAction)onCancelMethodPressed:(id)sender {
    [self cancelDelayMethod];
}

- (void) delayMethod:(int)delay   {
    [self performSelector:@selector(execute) withObject:nil afterDelay:delay];
    NSLog(@"delay call");
}

- (void) cancelDelayMethod {
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(execute) object:nil];
    NSLog(@"cancel execute");
}

- (void) execute {
    NSLog(@"execute");
}


Objective-C


訂閱Codeilin的旅程,若有最新消息會通知。

廣告

XCode上傳至GitHub方法

  1. 為何使用GitHub?
  2. 註冊帳號
  3. XCode登入至GitHub
  4. XCode上傳至GitHub

1. 為何使用GitHub?

GitHub是版本管控程式碼好用的空間,也能做Git版本管控的簡單練習。

只要是撰寫程式,參考別人的程式碼,很多程式碼都放在GitHub上面,但不是所有,也是有別的空間可以放。

Android能做版本管控的方法,不一定要使用GitHub。

不過本網站之後會以GitHub為主要版本管控的空間,因此在此介紹GitHub。

2. 註冊帳號

GitHub帳號有分免費與專業,不過可以練習期間,先以免費為主,將來有特殊需求,再去升級也不妨。

註冊帳號請至下方GitHub網站註冊

GitHub網址

3. XCode登入至GitHub

點擊Your repositories
點擊New
Repository name設定一個儲存庫名稱
設定是公開/私有
是否新增README file之後可以自訂內容
是否新增.gitignore該儲存庫使用程式語言
是否選擇使用的license
範例參考
建立好後,如這張圖
這次選擇Setting
左邊那排往下拉,選擇Developer settings
先選擇 Personal access tokens -> Generate new token
Note填寫說明
下方選擇token權限
設定完後點擊 -> Generate token
複製token字串
回到XCode選擇
Xcode -> Preferences…
新增GitHub帳號
輸入帳號與剛剛上面申請的Token
使用Git要使用的名字與Email

4. XCode上傳至GitHub

新增專案時,記得勾選,
但專案建立後Git依然沒有與GitHub連結
新增與遠端Git
按下Create建立專案到GitHub
完成後,就將專案上傳上去囉

備註

本篇重點不是Git教學,是將Code放置GitHub
之後會寫幾篇與Git相關的文章


訂閱Codeilin的旅程,若有最新消息會通知。

廣告

Kotlin runBlocking、withContext、async用法

1. 範例程式碼

GitHub:

https://github.com/f40706/coroutine_scope_test

2. runBlocking用法

測試1

執行simulationBlocking、simulationBlocking2這兩個

/*
* 出現問題: Inappropriate blocking method call
* 原因這樣使用,雖然可以正常使用,但卻讓CoroutineScope失去了意義
* simulationBlocking搭配simulationBlocking2測試
* 再看simulationWithContext搭配simulationWithContext2的測試
* 他會堵塞CoroutineScope並失去暫停當前線程的功能
* 2022/03/20 05:05:24.686: A1
* 2022/03/20 05:05:25.692: A2 11
* 2022/03/20 05:05:25.694: B1
* 2022/03/20 05:05:26.696: B2 22
*/
simulationBlocking()
simulationBlocking2()
private fun simulationBlocking() {
    mJob = mCoroutineScopeSDK.coroutineScopeLaunch({
        val result = runBlocking(Dispatchers.IO) {
            showCurSystemTime("A1")
            delay(1000)
            11
        }
        showCurSystemTime("A2 $result")
    }, {

    })
}
private fun simulationBlocking2() {
    mJob = mCoroutineScopeSDK.coroutineScopeLaunch({
        val result = runBlocking(Dispatchers.IO) {
            showCurSystemTime("B1")
            delay(1000)
            22
        }
        showCurSystemTime("B2 $result")
    }, {
    })
}

測試2

執行simulationBlocking3

/**
 * runBlocking建議搭配async使用,因為async是併發,就算一條線被堵塞,也不會有什麼影響
 * withContext只是切換線程,把當前的暫停,但依然只有一條線在跑,並不是併發
 * 如果使用runBlocking將會把所有線程賭塞
 * 2022/03/20 05:31:10.833: B1
 * 2022/03/20 05:31:11.836: B2
 * 2022/03/20 05:31:12.840: result -> 77
 * */
simulationBlocking3()

private fun simulationBlocking3() {
mJob = mCoroutineScopeSDK.coroutineScopeLaunch({
val async = async(Dispatchers.IO) {
val result = runBlocking {
showCurSystemTime("B1")
delay(1000)
33
}
val result2 = runBlocking {
showCurSystemTime("B2")
delay(1000)
44
}
result + result2
}
showCurSystemTime("result -> ${async.await()}")
}, {
})
}

3. withContext用法

測試1

執行simulationWithContext、simulationWithContext2

/**
* 很明顯看到擁有Coroutine Scope暫停的功能
* 2022/03/20 05:05:40.129: B1
* 2022/03/20 05:05:40.129: A1
* 2022/03/20 05:05:41.131: A2 20
* 2022/03/20 05:05:41.133: B2 10
* */
simulationWithContext()
simulationWithContext2()
private fun simulationWithContext() {
mJob = mCoroutineScopeSDK.coroutineScopeLaunch({
val result = withContext(Dispatchers.IO) {
showCurSystemTime("A1")
delay(1000)
20
}
showCurSystemTime("A2 $result")
}, {

})
}

private fun simulationWithContext2() {
mJob = mCoroutineScopeSDK.coroutineScopeLaunch({
val result = withContext(Dispatchers.IO) {
showCurSystemTime("B1")
delay(1000)
10
}
showCurSystemTime("B2 $result")
}, {

})
}

4. async用法

測試1

執行simulationASYNC

/**
* 很明顯看出他是併發
* 但通常async會搭配await取得他返回值
* 可以同時有nasync在使用await
* 等待他們完成後,做處理
* 參考simulationASYNC2
* -----經過此處A-----
* -----經過此處B-----
* 2022/03/20 05:14:51.139: D1
* 2022/03/20 05:14:51.143: D2
* 2022/03/20 05:14:51.647: DD1
* 2022/03/20 05:14:51.649: DD2
* */
simulationASYNC()
private fun simulationASYNC() {
mJob = mCoroutineScopeSDK.coroutineScopeLaunch({
async {
showCurSystemTime("D1")
delay(500)
showCurSystemTime("DD1")
30
}
println("-----經過此處A----- ")
async {
showCurSystemTime("D2")
delay(500)
showCurSystemTime("DD2")
30
}
println("-----經過此處B----- ")
}, {

})
}

測試2

執行simulationASYNC2

/**
 * async屬於併發
 * async擁有await的功能
 * 等待async內部完成再繼續往下做
 * delay是暫停當前線程,因此其他線程依然可以繼續動作
 * 使用兩個async並將結果相加
 * 2022/03/20 05:06:00.061: C1
 * 2022/03/20 05:06:00.063: CC1
 * 2022/03/20 05:06:00.565: CCC1 -> 50
 * */
simulationASYNC2()
private fun simulationASYNC2() {
mJob = mCoroutineScopeSDK.coroutineScopeLaunch({
val async = async {
showCurSystemTime("C1")
delay(10)
20
}
val async2 = async {
showCurSystemTime("CC1")
delay(500)
30
}
showCurSystemTime("CCC1 -> ${async.await()+async2.await()}")
}, {

})
}

Kotlin

正在載入…

執行時發生錯誤。請重新整理頁面後再試一次。


訂閱Codeilin的旅程,若有最新消息會通知。

廣告

Kotlin Coroutine Scope Exception處裡方法

1. 範例程式碼

GitHub:

https://github.com/f40706/coroutine_scope_exception

2. Exception擷取方法

package com.john.coroutine_scope_exception.common.sdk

import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext

class CoroutineScopeSDK {
    fun coroutineScopeLaunch(
        block: suspend CoroutineScope.() -> Unit,
        errorCallback: (Throwable) -> Unit
    ) = coroutineScopeLaunch(Dispatchers.Main, block, errorCallback)

    fun coroutineScopeLaunch(
        context: CoroutineContext,
        block: suspend CoroutineScope.() -> Unit,
        errorCallback: (Throwable) -> Unit
    ): Job {
        val handler = CoroutineExceptionHandler { _, exception ->
            errorCallback(exception)
        }
        return CoroutineScope(context).launch(handler) {
            block()
        }
    }
}

3. 使用方式

private fun simulationCoroutineScope() {
    mJob = mCoroutineScopeSDK.coroutineScopeLaunch({
        //testFun1()
        testFun2()
    }, {
        when(it) {
            is IOException -> {
                println("IOException $it")
            }
            is Exception -> {
                println("Exception $it")
            }
        }
    })
}
private suspend fun testFun1() {
    withContext(Dispatchers.IO) {
        throw Exception("error1")
    }
}
private suspend fun testFun2() {
    withContext(Dispatchers.IO) {
        throw IOException("error2")
    }
}

當異常拋出時,並不會導致手機閃退,而可以監聽到拋出的異常

並停止當前的Coroutine Scope

對於程式的乾淨程度也很高

Debug也會簡單很多


Kotlin


訂閱Codeilin的旅程,若有最新消息會通知。

廣告

Intellij IDEA 安裝與環境設置

1. 下載JDK

首先到Amazon官網下載,網址如下

https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html

下載對應的電腦版本

下載好後安裝,按照預設的安裝即可

2. 安裝Intellij IDEA

請至官網下,網址如下

https://www.jetbrains.com/idea/download/#section=windows

下載Free版本即可
勾選此,也可依照自己喜好勾選
安裝好後,打開Intellij IDEA
因為已經先前已經安裝好JDK,所以此時就會顯示安裝的JDK
將此兩選項打勾
將一些選項取消,意味著盡可能顯示更多提示
將此打勾

這樣Intellij IDEA 環境就設定好,可以開始使用囉


Intellij IDEA


訂閱Codeilin的旅程,若有最新消息會通知。

廣告

iOS使用Firebase Authentication的基本使用

1. 簡介

可以讓用戶使用其電子郵件地址和密碼進行 Firebase 身份驗證,還可以管理應用中的帳號

更多詳細內容可以參考官網:

https://firebase.google.com/docs/auth/ios/password-auth

2. 前置作業

請參考iOS專案如何導入Firebase?

3. 建立帳號

備註:前置作業必須先用好

建立以email的方式創建帳號

啟用並儲存

以下程式碼,可以寫在Button按下去後,執行他

email與password皆是String,就是要建立的帳號

執行後,會呼叫Lambda,error如果是nil代表成功,如果有error則是失敗

//記得import Firebase
Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
  
}

Firebase建立帳號有一些規則

Email必須是有效的

密碼必須大於六個字符

呼叫上面function,就會建立帳號,建立好後
就會在Firebase後臺上出現剛剛建立好的帳號

到此建立帳號就完成囉

登入帳號

觸發以下後,會登入帳號,email與password是先前建立好的帳號

//記得import Firebase
Auth.auth().signIn(withEmail: email, password: password) { [weak self] authResult, error in
    guard let self = self else { return }
                
}

登出帳號

觸發以下後,會登出帳號

//記得import Firebase
let firebaseAuth = Auth.auth()
do {
    try firebaseAuth.signOut()
    navigationController?.popToRootViewController(animated: true)
} catch let signOutError as NSError {
    print("Error signing out: %@", signOutError)
}


iOS


訂閱Codeilin的旅程,若有最新消息會通知。

廣告

iOS專案如何導入Firebase?

1. 簡介

Firebase是Google所開發的一個強大的Library,裡面有許多實用的功能

包含身分認證、機器學習套件、Cloud Firebase、性能監控等等

更多詳細內容可以參考官網:

https://firebase.google.com/docs

2. Firebase導入iOS專案

首先打開官網:

https://firebase.google.com/

取消打勾,因為牽涉很多其他功能,此文章暫時不需要
從XCode複製Bundle identifier
Apple軟體包ID就是指XCode的Bundle identifier
其他兩個選項可選,此文章不填
將下載的plist用拖移的方式,拖移置對應的專案中
選擇需要使用的Library
選擇iOS專案的語言,將此程式碼複製到專案中的AppDelegate

到此Firebase就成功加入至iOS專案囉


iOS


訂閱Codeilin的旅程,若有最新消息會通知。

廣告

XCode 安裝Cocoapods第三方Library的工具

1. 簡介

Cocoapods是能夠提供第三方Library的工具

使用他有一定的規則,依照此規則就能導入,所需的Library

2. 安裝Cocoapods

打開終端機->輸入以下

sudo gem install cocoapods

設定pod

pod setup –verbose

成功會顯示 Setup completed

輸入pod –version

有返回版本號代表設置完成

到此就安裝完囉

使用CocoaPods

.xcwordkspace是CocoaPods的使用時會生成的,要用此開啟專案,才會使用CocoaPods

生成.xcwordkspace方法如下

打開終端機,cd到專案路徑

之後輸入pod init

資料夾內就會出現Podfile

用XCode或文字編輯器打開它

platform :ios, ‘9.0’ 前面#拿掉,代表允許最小版本

use_frameworks!下面輸入

//使用預設版本
pod 'LabelSwitch'
//如果需要指定版本
pod 'LabelSwitch', '~> 0.1.6'
代表需要安裝'LabelSwitch'
然後儲存此文件檔案
終端機輸入pod install
就安裝完囉
之後專案由.xcwordkspace打開

XCode


訂閱Codeilin的旅程,若有最新消息會通知。

廣告

XCode 語法快捷鍵設定與程式碼分離關注點

1. 簡介

寫程式時,常常會發生同樣的東西要輸入好幾次,在設定語法快捷鍵後,相同的程式碼,可以改成快捷鍵,這樣在撰寫程式時,可以省下不少時間

如果能讓程式碼分離關注點,會讓程式碼看起來更容易閱讀

2. 新增快捷鍵的方法

對選取的程式碼按右鍵 -> Create Code Snippet
自己新增的會放在User,點選Edit可以編輯他
上方MARK Comment是描述
語言Swift
且是iOS
在所有位置
輸入mark時,會出現中間的文字
中間文字輸入<#Section Heading#>會自動變成可以輸入的文字
如圖顯示

這樣快速指令就設定完囉

要甚麼快捷鍵,都可以依這方法操作

分離關注點方法

在XCode裡面,如果輸入

//MARK: -時,如下

點選XCode上方如圖
有MARK: -的會自動分割

因此可以利用extension 做程式碼的擴展

將繼承的Delegate各別寫成一個擴展

class ViewController: UIViewController {

}
//MARK: - ManagerDelegate
extension ViewController: ManagerDelegate {

}

如上程式碼,將ManagerDelegate 寫成一個擴展,所有有關ManagerDelegate 的都寫在此

UIViewController 做為主架構,不在多繼承其他Delegate

達到關注點分離,讓程式碼更容易閱讀


XCode


訂閱Codeilin的旅程,若有最新消息會通知。

廣告

透過 WordPress.com 建置的網站.

向上 ↑