-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Okan Yücel
committed
Sep 28, 2022
1 parent
5504bc8
commit 8c94f8b
Showing
23 changed files
with
1,059 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.DS_Store | ||
/.build | ||
/Packages | ||
/*.xcodeproj | ||
xcuserdata/ | ||
DerivedData/ | ||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<Scheme | ||
LastUpgradeVersion = "1320" | ||
version = "1.3"> | ||
<BuildAction | ||
parallelizeBuildables = "YES" | ||
buildImplicitDependencies = "YES"> | ||
<BuildActionEntries> | ||
<BuildActionEntry | ||
buildForTesting = "YES" | ||
buildForRunning = "YES" | ||
buildForProfiling = "YES" | ||
buildForArchiving = "YES" | ||
buildForAnalyzing = "YES"> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "Swiftrie" | ||
BuildableName = "Swiftrie" | ||
BlueprintName = "Swiftrie" | ||
ReferencedContainer = "container:"> | ||
</BuildableReference> | ||
</BuildActionEntry> | ||
</BuildActionEntries> | ||
</BuildAction> | ||
<TestAction | ||
buildConfiguration = "Debug" | ||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | ||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | ||
shouldUseLaunchSchemeArgsEnv = "YES"> | ||
<Testables> | ||
<TestableReference | ||
skipped = "NO"> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "SwiftrieTests" | ||
BuildableName = "SwiftrieTests" | ||
BlueprintName = "SwiftrieTests" | ||
ReferencedContainer = "container:"> | ||
</BuildableReference> | ||
</TestableReference> | ||
</Testables> | ||
</TestAction> | ||
<LaunchAction | ||
buildConfiguration = "Debug" | ||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | ||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | ||
launchStyle = "0" | ||
useCustomWorkingDirectory = "NO" | ||
ignoresPersistentStateOnLaunch = "NO" | ||
debugDocumentVersioning = "YES" | ||
debugServiceExtension = "internal" | ||
allowLocationSimulation = "YES"> | ||
</LaunchAction> | ||
<ProfileAction | ||
buildConfiguration = "Release" | ||
shouldUseLaunchSchemeArgsEnv = "YES" | ||
savedToolIdentifier = "" | ||
useCustomWorkingDirectory = "NO" | ||
debugDocumentVersioning = "YES"> | ||
<MacroExpansion> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "Swiftrie" | ||
BuildableName = "Swiftrie" | ||
BlueprintName = "Swiftrie" | ||
ReferencedContainer = "container:"> | ||
</BuildableReference> | ||
</MacroExpansion> | ||
</ProfileAction> | ||
<AnalyzeAction | ||
buildConfiguration = "Debug"> | ||
</AnalyzeAction> | ||
<ArchiveAction | ||
buildConfiguration = "Release" | ||
revealArchiveInOrganizer = "YES"> | ||
</ArchiveAction> | ||
</Scheme> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// swift-tools-version:5.5 | ||
// The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "Swiftrie", | ||
products: [ | ||
// Products define the executables and libraries a package produces, and make them visible to other packages. | ||
.library( | ||
name: "Swiftrie", | ||
targets: ["Swiftrie"]) | ||
], | ||
dependencies: [ | ||
// Dependencies declare other packages that this package depends on. | ||
], | ||
targets: [ | ||
// Targets are the basic building blocks of a package. A target can define a module or a test suite. | ||
// Targets can depend on other targets in this package, and on products in packages this package depends on. | ||
.target( | ||
name: "Swiftrie", | ||
dependencies: []), | ||
.testTarget( | ||
name: "SwiftrieTests", | ||
dependencies: ["Swiftrie"]) | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
|
||
# Swiftrie | ||
|
||
First thing first, what is a [Trie](https://en.wikipedia.org/wiki/Trie).? | ||
|
||
> In computer science, a trie, also called digital tree or prefix tree, is a kind of search tree —an ordered tree data structure used to store a dynamic set or associative array where the keys are usually strings. [...] All the descendants of a node have a common prefix of the string associated with that node, and the root is associated with the empty string. Keys tend to be associated with leaves, though some inner nodes may correspond to keys of interest. Hence, keys are not necessarily associated with every node. | ||
This library provides all requirements about Trie implementation on Swift. | ||
|
||
What does this library offer: | ||
|
||
* First of all everything; `Swiftrie works with Codables`, not only with words. Every final node stores a JSON string for itself. It means you can use it with Codables. | ||
|
||
* Suit for all data models. Just implement `Swiftriable Interface` and that's all you need to make your model suit for Swiftrie. | ||
|
||
* A new item can be `insertable`/`removable`. | ||
|
||
* `Cancelable searches`. Swiftrie does it automatically. If you call the searching method again while the algorithm is searching a prefix, Swiftrie cancels the last search. | ||
|
||
* Also you can add `throttle`/`delay` while searching in Swiftrie to prevent unnecessary searches. `Default is 0`. Because `Swiftrie can show results in 0.001 seconds in 209k data for an entered character`. Because Swiftrie does not wait for all nodes that will be visited. Check the following topic. | ||
|
||
* Swiftrie provides showing results part by part. No need waiting for until the algorithm visits all nodes. It returns the results while visiting the nodes. To manage this logic just use `.gradually`. Default is `case indexable(_ index: 3)` index 3 means, the find method will return the response that it found at every 3 nodes without waiting for all nodes that will be visited. | ||
|
||
* Everything in a `custom queue`. QoS is `.userInitiated`. And it is `concurrent`. | ||
|
||
* Inserting and removing an item executes with `.barrier` in the custom queue. It means searching/getting will wait for inserting/removing and the algorithm will show correct results always. | ||
|
||
* Unit tests have provided. | ||
|
||
## Codes | ||
```swift | ||
let trie = Swiftrie(swiftriables: response.cities) | ||
|
||
trie.gradually = .indexable(3) | ||
|
||
trie.removeItem(/* a swiftriable item */) | ||
|
||
trie.insertItem(/* a swiftriable item */) | ||
|
||
let cities: [City] = trie.getAllItems() | ||
|
||
trie.findItems(prefix: "istanbu", throttle: 0, type: City.self) { result in | ||
print(result) | ||
} | ||
|
||
trie.cancelSearch() | ||
``` | ||
|
||
### Swift Package Manager | ||
|
||
To install CustomNavigationBar using [Swift Package Manager](https://github.com/apple/swift-package-manager) you can follow the [tutorial published by Apple](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app) using the URL for the Swiftrie repo with the current version: | ||
|
||
1. In Xcode, select “File” → “Swift Packages” → “Add Package Dependency” | ||
1. Enter https://github.com/yucelokan/Swiftrie.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// | ||
// Codable+Extensions.swift | ||
// | ||
// | ||
// Created by okan.yucel on 5.03.2022. | ||
// | ||
|
||
import Foundation | ||
|
||
extension Encodable { | ||
var data: Data? { | ||
let encoder = JSONEncoder() | ||
encoder.outputFormatting = .prettyPrinted | ||
return try? encoder.encode(self) | ||
} | ||
|
||
var jsonString: String { | ||
guard let data = data else { return "" } | ||
guard let jsonString = String(data: data, encoding: .utf8) else { return "" } | ||
return jsonString | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
Sources/Swiftrie/Extensions/DispatchQueue+Extensions.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// | ||
// DispatchQueue+Extensions.swift | ||
// | ||
// | ||
// Created by okan.yucel on 6.03.2022. | ||
// | ||
|
||
import Foundation | ||
|
||
extension DispatchQueue { | ||
/** | ||
- parameters: | ||
- target: Object used as the sentinel for de-duplication. | ||
- delay: The time window for de-duplication to occur | ||
- work: The work item to be invoked on the queue. | ||
Performs work only once for the given target, given the time window. The last added work closure | ||
is the work that will finally execute. | ||
Note: This is currently only safe to call from the main thread. | ||
Example usage: | ||
``` | ||
DispatchQueue.main.asyncDeduped(target: self, after: 1.0) { [weak self] in | ||
self?.doTheWork() | ||
} | ||
``` | ||
*/ | ||
func asyncDeduped( | ||
target: AnyObject, | ||
after delay: TimeInterval, | ||
execute work: @escaping @convention(block) () -> Void | ||
) { | ||
let dedupeIdentifier = DispatchQueue.dedupeIdentifierFor(target) | ||
if let existingWorkItem = DispatchQueue.workItems.removeValue(forKey: dedupeIdentifier) { | ||
existingWorkItem.cancel() | ||
} | ||
let workItem = DispatchWorkItem { | ||
DispatchQueue.workItems.removeValue(forKey: dedupeIdentifier) | ||
|
||
for ptr in DispatchQueue.weakTargets.allObjects { | ||
if dedupeIdentifier == DispatchQueue.dedupeIdentifierFor(ptr as AnyObject) { | ||
work() | ||
break | ||
} | ||
} | ||
} | ||
DispatchQueue.workItems[dedupeIdentifier] = workItem | ||
DispatchQueue.weakTargets.addPointer(Unmanaged.passUnretained(target).toOpaque()) | ||
|
||
asyncAfter(deadline: .now() + delay, execute: workItem) | ||
} | ||
} | ||
|
||
// MARK: - Static Properties for De-Duping | ||
|
||
private extension DispatchQueue { | ||
static var workItems = [AnyHashable: DispatchWorkItem]() | ||
static var weakTargets = NSPointerArray.weakObjects() | ||
static func dedupeIdentifierFor(_ object: AnyObject) -> String { | ||
"\(Unmanaged.passUnretained(object).toOpaque())." + String(describing: object) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// | ||
// String+Extensions.swift | ||
// | ||
// | ||
// Created by okan.yucel on 5.03.2022. | ||
// | ||
|
||
import Foundation | ||
|
||
extension String { | ||
func toObject<T: Decodable>() -> T? { | ||
return try? JSONDecoder().decode(T.self, from: Data(self.utf8)) | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
Sources/Swiftrie/OrderedDictionary/YOOrderedDictionary.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// | ||
// YOOrderedDictionary.swift | ||
// | ||
// | ||
// Created by okan.yucel on 12.04.2022. | ||
// | ||
|
||
import Foundation | ||
|
||
class YOOrderedDictionary<Key: Hashable, Value> { | ||
|
||
typealias Element = (key: Key, value: Value) | ||
|
||
init() { } | ||
|
||
private (set) var values: [Element] = [] | ||
|
||
subscript(key: Key) -> Value? { | ||
get { | ||
guard let item = values.first(where: {$0.key == key}) else { return nil } | ||
return item.value | ||
} | ||
set(newValue) { | ||
guard let value = newValue else { | ||
// if it is nil, remove it | ||
values.removeAll(where: {$0.key == key}) | ||
return | ||
} | ||
let element = (key: key, value: value) | ||
guard let index = values.firstIndex(where: {$0.key == key}) else { | ||
// if there is no exist, append it | ||
values.append(element) | ||
return | ||
} | ||
// if it already exists, remove it and insert it | ||
values.remove(at: index) | ||
values.insert(element, at: index) | ||
} | ||
} | ||
|
||
func sort( | ||
by condition: (Element, Element) -> Bool | ||
) { | ||
values.sort(by: condition) | ||
} | ||
|
||
var first: Value? { | ||
return values.first?.value | ||
} | ||
|
||
var last: Value? { | ||
return values.last?.value | ||
} | ||
|
||
var count: Int { | ||
return values.count | ||
} | ||
|
||
var isEmpty: Bool { | ||
return values.isEmpty | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// | ||
// SwiftrieItem.swift | ||
// | ||
// | ||
// Created by okan.yucel on 5.03.2022. | ||
// | ||
|
||
import Foundation | ||
|
||
public protocol Swiftriable: Codable { | ||
var prefixableText: String { get } | ||
} |
Oops, something went wrong.