Swift example

GitOrigin-RevId: a79b90748b0e978610a0da2f7e7bfa8b40a44c03
This commit is contained in:
Arseny Smirnov 2018-02-12 16:10:53 +03:00
parent 4bd61bdc86
commit 85c9a8bdb1
5 changed files with 511 additions and 0 deletions

3
example/swift/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
xcuserdata/
*workspace/
td/

12
example/swift/README.md Normal file
View File

@ -0,0 +1,12 @@
# TDLib swift MacOS example
TDLib should be prebuilt and installed to local subdirectory `td/`:
```
cd <path to TDLib sources>
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=../example/swift/td ..
cmake --build . --target install
```
Then you can open and build the exampe with XCode.

View File

@ -0,0 +1,174 @@
import Foundation
class TdClient {
typealias Client = UnsafeMutableRawPointer
var client = td_json_client_create()!
let tdlibMainLoop = DispatchQueue(label: "tdlib")
let tdlibQueryQueue = DispatchQueue(label: "tdlibQuery")
var queryF = Dictionary<Int64, (Dictionary<String,Any>)->()>()
var updateF : ((Dictionary<String,Any>)->())?
var queryId : Int64 = 0
var closing = false
func queryAsync(query: [String: Any], f: ((Dictionary<String,Any>)->())? = nil) {
tdlibQueryQueue.async {
var newQuery = query
if f != nil {
let nextQueryId = self.queryId + 1
newQuery["@extra"] = nextQueryId
self.queryF[nextQueryId] = f
self.queryId = nextQueryId
}
td_json_client_send(self.client, to_json(newQuery))
}
}
func querySync(query: [String: Any]) -> Dictionary<String,Any> {
let semaphore = DispatchSemaphore(value:0)
var result = Dictionary<String,Any>()
queryAsync(query: query) {
result = $0
semaphore.signal()
}
semaphore.wait()
return result
}
func close() {
closing = true
}
init() {
}
deinit {
td_json_client_destroy(client)
}
func run(updateHandler: @escaping (Dictionary<String,Any>)->()) {
updateF = updateHandler
tdlibMainLoop.async { [weak self] in
while (true) {
if let s = self {
if s.closing {
break
}
if let res = td_json_client_receive(s.client,10) {
let event = String(cString: res)
s.queryResultAsync(event)
}
} else {
break
}
}
}
}
private func queryResultAsync(_ result: String) {
tdlibQueryQueue.async {
let json = try? JSONSerialization.jsonObject(with: result.data(using: .utf8)!, options:[])
if let dictionary = json as? [String:Any] {
if let extra = dictionary["@extra"] as? Int64 {
let index = self.queryF.index(forKey: extra)!
self.queryF[index].value(dictionary)
self.queryF.remove(at: index)
} else {
self.updateF!(dictionary)
}
}
}
}
}
// Just an example of usage
func to_json(_ obj: Any) -> String {
do {
let obj = try JSONSerialization.data(withJSONObject: obj)
return String(data: obj, encoding: .utf8)!
} catch {
return ""
}
}
func myReadLine() -> String {
while (true) {
if let line = readLine() {
return line
}
}
}
td_set_log_verbosity_level(2);
var client = TdClient()
func updateAuthorizationState(authState : Dictionary<String, Any>) {
switch(authState["@type"] as! String) {
case "authorizationStateWaitTdlibParameters":
client.queryAsync(query:[
"@type":"setTdlibParameters",
"parameters":[
"use_message_database":true,
"use_secret_chats":true,
"api_id":94575,
"api_hash":"a3406de8d171bb422bb6ddf3bbd800e2",
"system_language_code":"en",
"device_model":"Desktop",
"system_version":"Unknown",
"application_version":"1.0",
"enable_storage_optimizer":true
]
]);
case "authorizationStateWaitEncryptionKey":
client.queryAsync(query: ["@type":"checkDatabaseEncryptionKey", "key":"cucumber"])
case "authorizationStateWaitPhoneNumber":
print("Enter your phone: ")
let phone = myReadLine()
client.queryAsync(query:["@type":"setAuthenticationPhoneNumber", "phone_number":phone], f:checkAuthError)
case "authorizationStateWaitCode":
var first_name : String = ""
var last_name: String = ""
var code : String = ""
if let is_registered = authState["is_registered"] as? Bool, is_registered {
} else {
print("Enter your first name : ")
first_name = myReadLine()
print("Enter your last name: ")
last_name = myReadLine()
}
print("Enter (sms) code: ")
code = myReadLine()
client.queryAsync(query:["@type":"checkAuthenticationCode", "code":code, "first_name":first_name, "last_name":last_name], f:checkAuthError)
case "authorizationStateWaitPassword":
print("Enter password: ")
let password = myReadLine()
client.queryAsync(query:["@type":"checkAuthenticationPassword", "password":password], f:checkAuthError)
case "authorizationStateReady":
()
default:
assert(false, "TODO: Unknown auth state ");
}
}
func checkAuthError(error: Dictionary<String, Any>) {
if (error["@type"] as! String == "error") {
client.queryAsync(query:["@type":"getAuthorizationState"], f:updateAuthorizationState)
}
}
client.run {
let update = $0
print(update)
if update["@type"] as! String == "updateAuthorizationState" {
updateAuthorizationState(authState: update["authorization_state"] as! Dictionary<String, Any>)
}
}
while true {
sleep(1)
}

View File

@ -0,0 +1,12 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#include "td/telegram/td_json_client.h"
#include "td/telegram/td_log.h"

View File

@ -0,0 +1,310 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1F65E3A42031BF6A00F79763 /* libtdjson.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F65E3A32031BF6A00F79763 /* libtdjson.dylib */; };
1F65E3A92031C0F000F79763 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F65E3A82031C0F000F79763 /* main.swift */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
1FCE2CEF1EC5E1B50061661A /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1F65E3A32031BF6A00F79763 /* libtdjson.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtdjson.dylib; path = td/lib/libtdjson.dylib; sourceTree = "<group>"; };
1F65E3A82031C0F000F79763 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = main.swift; path = src/main.swift; sourceTree = SOURCE_ROOT; };
1F65E3AA2031C14300F79763 /* td-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "td-Bridging-Header.h"; path = "src/td-Bridging-Header.h"; sourceTree = SOURCE_ROOT; };
1FCE2CF11EC5E1B50061661A /* td */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = td; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
1FCE2CEE1EC5E1B50061661A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
1F65E3A42031BF6A00F79763 /* libtdjson.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
1FCE2CE81EC5E1B50061661A = {
isa = PBXGroup;
children = (
1FCE2CF31EC5E1B50061661A /* src */,
1FCE2CF21EC5E1B50061661A /* Products */,
1FCE2CFB1EC5E1EE0061661A /* Frameworks */,
);
sourceTree = "<group>";
};
1FCE2CF21EC5E1B50061661A /* Products */ = {
isa = PBXGroup;
children = (
1FCE2CF11EC5E1B50061661A /* td */,
);
name = Products;
sourceTree = "<group>";
};
1FCE2CF31EC5E1B50061661A /* src */ = {
isa = PBXGroup;
children = (
1F65E3AA2031C14300F79763 /* td-Bridging-Header.h */,
1F65E3A82031C0F000F79763 /* main.swift */,
);
name = src;
path = td;
sourceTree = "<group>";
};
1FCE2CFB1EC5E1EE0061661A /* Frameworks */ = {
isa = PBXGroup;
children = (
1F65E3A32031BF6A00F79763 /* libtdjson.dylib */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
1FCE2CF01EC5E1B50061661A /* td */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1FCE2CF81EC5E1B50061661A /* Build configuration list for PBXNativeTarget "td" */;
buildPhases = (
1FCE2CED1EC5E1B50061661A /* Sources */,
1FCE2CEE1EC5E1B50061661A /* Frameworks */,
1FCE2CEF1EC5E1B50061661A /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = td;
productName = td;
productReference = 1FCE2CF11EC5E1B50061661A /* td */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
1FCE2CE91EC5E1B50061661A /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0830;
LastUpgradeCheck = 0920;
ORGANIZATIONNAME = "Arseny Smirnov ";
TargetAttributes = {
1FCE2CF01EC5E1B50061661A = {
CreatedOnToolsVersion = 8.3.2;
LastSwiftMigration = 0920;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 1FCE2CEC1EC5E1B50061661A /* Build configuration list for PBXProject "td" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 1FCE2CE81EC5E1B50061661A;
productRefGroup = 1FCE2CF21EC5E1B50061661A /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
1FCE2CF01EC5E1B50061661A /* td */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
1FCE2CED1EC5E1B50061661A /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1F65E3A92031C0F000F79763 /* main.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
1FCE2CF61EC5E1B50061661A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
};
name = Debug;
};
1FCE2CF71EC5E1B50061661A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
};
name = Release;
};
1FCE2CF91EC5E1B50061661A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks $(PROJECT_DIR)/lib";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/td/lib",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "src/td-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
USER_HEADER_SEARCH_PATHS = td/include/;
};
name = Debug;
};
1FCE2CFA1EC5E1B50061661A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks $(PROJECT_DIR)/lib";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/td/lib",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "src/td-Bridging-Header.h";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
USER_HEADER_SEARCH_PATHS = td/include/;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1FCE2CEC1EC5E1B50061661A /* Build configuration list for PBXProject "td" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1FCE2CF61EC5E1B50061661A /* Debug */,
1FCE2CF71EC5E1B50061661A /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1FCE2CF81EC5E1B50061661A /* Build configuration list for PBXNativeTarget "td" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1FCE2CF91EC5E1B50061661A /* Debug */,
1FCE2CFA1EC5E1B50061661A /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 1FCE2CE91EC5E1B50061661A /* Project object */;
}