summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Vitaly Takmazov2020-09-16 22:26:04 +0300
committerGravatar Vitaly Takmazov2020-12-10 18:59:55 +0300
commit4851a21c41488a6f0c01e60f1bd1472846f816bf (patch)
treed7c5963f1e2856bbd7872bbf58109aa1ef53b5c5
parent00ed374bab44f4bf43f82425b804ffc196d19e77 (diff)
Initial API service in Swift
-rw-r--r--Juick.xcodeproj/project.pbxproj24
-rw-r--r--Juick/Service.swift135
-rw-r--r--Juick/Supporting Files/Juick-Bridging-Header.h3
3 files changed, 162 insertions, 0 deletions
diff --git a/Juick.xcodeproj/project.pbxproj b/Juick.xcodeproj/project.pbxproj
index dcb9060..8ab2162 100644
--- a/Juick.xcodeproj/project.pbxproj
+++ b/Juick.xcodeproj/project.pbxproj
@@ -35,6 +35,7 @@
774528C21F930C06004D110B /* Attachment.m in Sources */ = {isa = PBXBuildFile; fileRef = 774528C11F930C06004D110B /* Attachment.m */; };
774746AD239F82A10001C7F9 /* NSDate+TimeAgo.m in Sources */ = {isa = PBXBuildFile; fileRef = 774746AC239F82A10001C7F9 /* NSDate+TimeAgo.m */; };
774746B6239F872A0001C7F9 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 774746B5239F872A0001C7F9 /* CoreServices.framework */; };
+ 774C98CD25126C070073C70A /* Service.swift in Sources */ = {isa = PBXBuildFile; fileRef = 774C98CC25126C070073C70A /* Service.swift */; };
7761133821766A3000D350CD /* ContentLoadingCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 7761133621766A3000D350CD /* ContentLoadingCell.m */; };
7761133921766A3000D350CD /* ContentLoadingCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7761133721766A3000D350CD /* ContentLoadingCell.xib */; };
7761135D21790B0300D350CD /* JuickPush.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7761135521790B0200D350CD /* JuickPush.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@@ -146,6 +147,8 @@
774746AC239F82A10001C7F9 /* NSDate+TimeAgo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDate+TimeAgo.m"; sourceTree = "<group>"; };
774746B4239F86EA0001C7F9 /* JuickPush.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = JuickPush.entitlements; sourceTree = "<group>"; };
774746B5239F872A0001C7F9 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreServices.framework; sourceTree = DEVELOPER_DIR; };
+ 774C98C0251263720073C70A /* Juick-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Juick-Bridging-Header.h"; sourceTree = "<group>"; };
+ 774C98CC25126C070073C70A /* Service.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Service.swift; sourceTree = "<group>"; };
7761133521766A3000D350CD /* ContentLoadingCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ContentLoadingCell.h; sourceTree = "<group>"; };
7761133621766A3000D350CD /* ContentLoadingCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ContentLoadingCell.m; sourceTree = "<group>"; };
7761133721766A3000D350CD /* ContentLoadingCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ContentLoadingCell.xib; sourceTree = "<group>"; };
@@ -296,6 +299,7 @@
77317BC6181BBE8500D60005 /* Images.xcassets */,
77C6ADDD1F770EB2000AEA8C /* Main.storyboard */,
77C364912243FAEF0017522C /* Colors.xcassets */,
+ 774C98CC25126C070073C70A /* Service.swift */,
);
path = Juick;
sourceTree = "<group>";
@@ -303,6 +307,7 @@
77317BB2181BBE8500D60005 /* Supporting Files */ = {
isa = PBXGroup;
children = (
+ 774C98C0251263720073C70A /* Juick-Bridging-Header.h */,
773F231B1F76DD0B00B5B0DF /* SerpentineBoldItalic.ttf */,
77317BB4181BBE8500D60005 /* InfoPlist.strings */,
77317BB3181BBE8500D60005 /* Juick-Info.plist */,
@@ -500,6 +505,7 @@
TargetAttributes = {
77317BA7181BBE8500D60005 = {
DevelopmentTeam = KH4MX79ZK7;
+ LastSwiftMigration = 1200;
SystemCapabilities = {
com.apple.BackgroundModes = {
enabled = 1;
@@ -615,6 +621,7 @@
77E35A82189A5B5A00B2D216 /* LoginViewController.m in Sources */,
773E6397204BCB64008B8F8D /* ConversationCell.m in Sources */,
778560602343D24E00BB37A2 /* NSData+Hex.m in Sources */,
+ 774C98CD25126C070073C70A /* Service.swift in Sources */,
776C41BD1FD3EF180063B82E /* MessageCell.m in Sources */,
77317BB8181BBE8500D60005 /* main.m in Sources */,
77B8B39C207A5629005CB20C /* MessageInputView.m in Sources */,
@@ -780,6 +787,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Juick/Juick.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -789,10 +797,14 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Juick/Supporting Files/Juick-Prefix.pch";
INFOPLIST_FILE = "Juick/Supporting Files/Juick-Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.juick.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SUPPORTS_MACCATALYST = YES;
+ SWIFT_OBJC_BRIDGING_HEADER = "Juick/Supporting Files/Juick-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
};
@@ -803,6 +815,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Juick/Juick.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CURRENT_PROJECT_VERSION = 148;
@@ -810,10 +823,13 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Juick/Supporting Files/Juick-Prefix.pch";
INFOPLIST_FILE = "Juick/Supporting Files/Juick-Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.juick.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SUPPORTS_MACCATALYST = YES;
+ SWIFT_OBJC_BRIDGING_HEADER = "Juick/Supporting Files/Juick-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
};
@@ -948,6 +964,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Juick/Juick.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -957,10 +974,14 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Juick/Supporting Files/Juick-Prefix.pch";
INFOPLIST_FILE = "Juick/Supporting Files/Juick-Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.juick.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SUPPORTS_MACCATALYST = YES;
+ SWIFT_OBJC_BRIDGING_HEADER = "Juick/Supporting Files/Juick-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
};
@@ -1004,6 +1025,7 @@
77F2B6A6251249F300E42F6F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
@@ -1032,6 +1054,7 @@
77F2B6A7251249F300E42F6F /* Debug (local) */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
@@ -1060,6 +1083,7 @@
77F2B6A8251249F300E42F6F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
diff --git a/Juick/Service.swift b/Juick/Service.swift
new file mode 100644
index 0000000..441451e
--- /dev/null
+++ b/Juick/Service.swift
@@ -0,0 +1,135 @@
+//
+// Service.swift
+// Juick
+//
+// Created by Vitaly Takmazov on 16.09.2020.
+// Copyright © 2020 com.juick. All rights reserved.
+//
+
+import Foundation
+
+class Service : NSObject, URLSessionDelegate, URLSessionTaskDelegate {
+ let backgroundQueue = OperationQueue()
+
+ let baseURL : URL?
+
+ lazy var authorizationHeader : String? = {
+ if let token = UserDefaults.standard.string(forKey: "token") {
+ return "Juick \(token)"
+ }
+ return nil;
+ }()
+
+ override init() {
+ let baseURLString = Bundle.main.object(forInfoDictionaryKey:"base_url") as! String
+ debugPrint("Initializing with \(baseURLString) base URL")
+ self.baseURL = URL(string: baseURLString)
+ super.init()
+ }
+ func url(url:URL, params:[String: String]) -> URL {
+ let parametersUrl = NSURLComponents(url: url, resolvingAgainstBaseURL: true)
+ var items : [URLQueryItem] = []
+ for (key, value) in params {
+ items.append(URLQueryItem(name: key, value: value))
+ }
+ parametersUrl?.queryItems = items
+ return (parametersUrl?.url!)!
+ }
+ func fetchData(url:URL, postData:Data?, boundary:String?, header:String?, callback: @escaping (Data?, Error?) -> Void) {
+ var request = URLRequest(url: url)
+ if (header != nil) {
+ request.addValue(header!, forHTTPHeaderField:"Authorization")
+ }
+ if (boundary != nil) {
+ request.httpMethod = "POST";
+ request.httpBody = postData;
+ let contentType = "multipart/form-data; boundary=\(boundary!)"
+ request.setValue(contentType, forHTTPHeaderField:"Content-Type")
+ } else if (postData != nil) {
+ request.httpMethod = "PUT";
+ request.httpBody = postData;
+ request.setValue("application/json", forHTTPHeaderField:"Content-Type")
+ } else {
+ request.httpMethod = "GET";
+ }
+
+ let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
+ if (error != nil) {
+ OperationQueue.main.addOperation {
+ callback(nil, error)
+ }
+ } else {
+ let statusCode = (response as? HTTPURLResponse)?.statusCode ?? 457
+ if (response == nil || statusCode != 200) {
+ let url = request.url
+ let err = NSError(domain: "JuickErrorDomain", code: statusCode, userInfo: ["url":url!.absoluteString])
+ OperationQueue.main.addOperation {
+ callback(nil, err)
+ }
+ } else {
+ OperationQueue.main.addOperation {
+ callback(data, error)
+ }
+ }
+ }
+ })
+ self.backgroundQueue.addOperation {
+ task.resume()
+ }
+ }
+ private func multipartData(params:[String:String], boundary:String) -> Data {
+ var body = Data()
+ for (key, value) in params {
+ body.append("--\(boundary)\r\n".data(using: .utf8)!)
+ body.append("Content-Disposition: form-data; name=\(key)\r\n\r\n".data(using: .utf8)!)
+ body.append("\(value)\r\n".data(using: .utf8)!)
+ }
+ body.append("--\(boundary)--".data(using: .utf8)!)
+ return body;
+ }
+ private func get(path:String, params:[String:String], callback:@escaping (NSDictionary?, Error?) -> Void) {
+ if let url = URL(string: path, relativeTo: self.baseURL) {
+ let requestUrl = params.isEmpty ? url : self.url(url: url, params: params)
+ fetchData(url: requestUrl, postData: nil, boundary: nil, header: self.authorizationHeader) {
+ (responseData, err) in
+ if (err != nil) {
+ callback(nil, err)
+ } else {
+ if let data = responseData, let jsonData = try? JSONSerialization.jsonObject(with: data, options: []) {
+ callback(jsonData as? NSDictionary, nil)
+ } else {
+ callback(nil, NSError(domain: "JuickErrorDomain", code: 500, userInfo: ["message":"JSON error"]))
+ }
+ }
+ }
+ }
+ }
+
+ func post(path: String, params:[String:String], callback:@escaping (NSDictionary?, Error?) -> Void) {
+ if let url = URL(string: path, relativeTo: self.baseURL) {
+ let boundary = "Boundary-\(UUID().uuidString)";
+ fetchData(url: url, postData:multipartData(params: params, boundary: boundary), boundary: boundary, header: self.authorizationHeader) {
+ (responseData, err) in
+ if (err != nil) {
+ callback(nil, err)
+ } else {
+ if let data = responseData, let jsonData = try? JSONSerialization.jsonObject(with: data, options: []) {
+ callback(jsonData as? NSDictionary, nil)
+ } else {
+ callback(nil, NSError(domain: "JuickErrorDomain", code: 500, userInfo: ["message":"JSON error"]))
+ }
+ }
+ }
+ }
+ }
+
+ func fetchImage(url:URL, callback:@escaping(Data?)-> Void) {
+ fetchData(url: url, postData: nil, boundary: nil, header: self.authorizationHeader) { (data, err) in
+ if (err != nil) {
+ callback(nil);
+ } else {
+ callback(data);
+ }
+ }
+ }
+}
diff --git a/Juick/Supporting Files/Juick-Bridging-Header.h b/Juick/Supporting Files/Juick-Bridging-Header.h
new file mode 100644
index 0000000..e11d920
--- /dev/null
+++ b/Juick/Supporting Files/Juick-Bridging-Header.h
@@ -0,0 +1,3 @@
+//
+// Use this file to import your target's public headers that you would like to expose to Swift.
+//