I am trying, for learning sake, to make a hybrid database app that will allow the user to store data locally and will allow the user to connect to an external database. I have a controller (MainController.swift) file that houses the code that will interact with the Suggest Table that I have in my Main View Controller. Here is the code (sorry, its long):
import UIKit
import CoreData
class MainController: UIViewController, NSFetchedResultsControllerDelegate {
// MARK: UI Components
// Suggestions Table
@IBOutlet weak var dataTableView: UITableView!
@IBOutlet weak var suggestLabel: UILabel!
// MARK: Variables
private var suggests = [Suggest]() {
didSet {
updateMainView()
}
}
private let persistContainer = NSPersistentContainer(name: "Suggest")
fileprivate lazy var fetchedResults:NSFetchedResultsController<Suggest> = {
let fetchRequest: NSFetchRequest<Suggest> = Suggest.fetchRequest()
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: true)]
let fetchedResults = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.persistContainer.viewContext, sectionNameKeyPath: nil, cacheName: nil)
fetchedResults.delegate = self
return fetchedResults
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
dataTableView.dataSource = self
dataTableView.delegate = self
setupMainView()
// Load persistent container modules
persistContainer.loadPersistentStores { (persistenStoreDescription, error) in
if let error = error {
print("[-] Unable to load persistent container -> \(error) : \(error.localizedDescription)")
} else {
self.setupMainView()
do {
try self.fetchedResults.performFetch()
} catch {
let fetchError = error as NSError
print("[-] Unable to perform fetch request -> \(fetchError) : \(fetchError.localizedDescription)")
}
self.updateMainView()
}
}
}
// MARK: Add-On functions and methods
private func updateMainView() {
var hashSuggest = false
if let suggests = fetchedResults.fetchedObjects {
hashSuggest = suggests.count > 0
}
dataTableView.isHidden = !hashSuggest
if hashSuggest { suggestLabel.text = "Suggested Databases" }
}
private func setupMainView() -> Void {
suggestLabel.text = defaultNoSuggestsString()
updateMainView()
}
private func defaultNoSuggestsString() -> String { return "No suggested databases...Error" }
@nonobjc public class func performFetch() -> NSFetchRequest<Suggest> {
return NSFetchRequest<Suggest>(entityName: "Suggest");
}
}
// MARK: Extensions
extension MainController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let suggests = fetchedResults.fetchedObjects else { return 0 }
return suggests.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "suggestCell", for: indexPath) as? SuggestedCellStructure else {
fatalError("Unexpected Index Path")
}
// Fetch the data modules
let module = fetchedResults.object(at: indexPath)
// Image config
let image = UIImage(systemName: module.image_string!)
let mainImage = UIImageView(image: image)
// Configure the cell
cell.suggestTitle.text = module.title_string
cell.suggestDesc.text = module.desc_string
cell.welcomingImage = mainImage
return cell
}
}
I have the Core Data structure here as well (Image 01) with the Name defined as the Class.
When every I run the app to test, I get this error message:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'An instance of NSFetchedResultsController requires a non-nil fetchRequest and managedObjectContext' - terminating with uncaught exception of type NSException
The Name is defined in the Core Data Structure file and the Codegen is defined as "Class Definition" so...im not seeing what is wrong.
Here is also the TableViewCell structure profile code:
import Foundation
import UIKit
class SuggestedCellStructure: UITableViewCell {
@IBOutlet weak var welcomingImage: UIImageView!
@IBOutlet weak var suggestTitle: UILabel!
@IBOutlet weak var suggestDesc: UITextView!
@IBOutlet weak var initSuggest: UIButton!
}
Post
Replies
Boosts
Views
Activity
I have made a custom swift package that contains the encoding and decoding functions for my app String Conversion Tool. It is uploaded to GitHub: (https://github.com/Casual3306/ConverterExtra). I do a request for the package (in my apps main project) and the package imports just fine, it is present in the Frameworks, Libraries, and Embedded Content and it is present in Package Dependencies, I have also run: "Reset Package Caches" and "Resolve Package Versions". The package also imports into the designated module as a "module" but when I try to access any of that "modules" files like > ConverterExtras > Encoders it is giving me an error saying that "This class may not be available in this context". All of the files are in the module package but Xcode isn't finding them for some reason:
Xcode version: 13
System: MacOS (Big Sur 11.6)
I have made and submitted an iOS iPhone app that was reviewed and published to the App Store, this app only supports iPhone devices and not iPad devices. I am making an iPad compatible app to go along with the iPhone app. Is there a way I can submit the iPad app so that it integrates with the iPhone version?
What I am trying to say is: can I upload my iPad app alongside my iPhone app so that the user can download the app on both devices (the iPad app and the iPhone app have the same SKU/ID) without modifying the iPhone app/upload binary?
I am thinking about creating a view controller that will be used primarily for settings and app configurations. I know that one can segue view controllers programmatically and transfer data between view controllers but, would that really be efficient? My thought for the settings VC would be theming and app bit (integer) settings.
Does anyone have any tips and or suggestions for an efficient way to apply user based settings from one View Controller that controls user settings?
I have a UITextField outlet declared in my primary view controller that is attached to the "encoder" tab. The "ViewController.swift" is linked to the ViewController. For some reason when a double tap (and or hold) the UITextField, the copy, paste, select/select all options are not showing. They are supposed to show even though the text field module is empty. I tried to implement this:
override var canBecomeFirstResponder: Bool {
return true
}
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
	 return (action ==							 #selector(UIResponderStandardEditActions.paste(_:)))
}
It gives me the paste option but the thread crashes with this message:
Thread 1: "-[String_Conversion_Tool.ViewController paste:]: unrecognized selector sent to instance 0x104e09860"
How can I enable the copy, paste, select/select all options for the UITextField like it was before? or how can I enable them programatically?
Would anyone be willing to beta test my app? if so, please give supply email.
My app is in its final stage and I am doing some "last minute" testing. Everything else works like it's supposed to but one problem I noticed was when I attempt to convert a string of 660 characters to binary the UI completely freezes up until the entire conversion is complete, due to the heavy encoding activity.
I tried to implement Dispatch Dispatch.main.async { /* Code */ }
in my main encoding function meanwhile implementing Dispatch.gloabl(qos: .default).async { /* Main encoding sequence code */ }
(where "main encoding sequence code" is the encoding algorithm) but I am still getting the freezes. Then I tried to do THAT but instead of encoding the whole string, I split the string up. Basically, when the encoding algorithm is called, the string will be encoded every 50 characters.
One other thing is, it's only doing that for Binary Encoding. Every other encoding method handles 660 characters just fine.
I just want to know how I can eliminate the freezing UI (until the operation is complete) more efficiently. I have posted the full operation below (I also implemented a function for when the string is over 100 characters):
import UIKit
import Foundation
class ViewController: UIViewController {
// MARK:- Outlet init
@IBOutlet weak var sourceString: UITextField!
@IBOutlet weak var resultOutput: UITextView!
@IBOutlet weak var encode: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
		// MARK:- The main encoding function
@IBAction func btnEncode(_ sender: Any) {
						if sourceString.text!.count > 100 {
displayErrorMessage(title: "Long String Alert", message: "This is a pretty long string, this may take a bit to convert to binary, please hold...(String length = " + String(source.count), buttonTitles: "Okay");
encodeBinaryWhenCharOverlimit(input: source)
}
DispatchQueue.main.async {
// Run UI Updates
self.encodeStringBinary(string: source); return
}
		}
// MARK:- Add-In functions and methods
private func toBinaryStringArray(array:[UInt8]) -> [String] {
DispatchQueue.global(qos: .default).sync {
var result:[String] = []
for e in array {
let bin = byteToBinaryString(byte: e)
result.append(bin)
}
return result;
}
}
private func byteToBinaryString(byte:UInt8) -> String {
DispatchQueue.global(qos: .default).sync {
var result = String(byte, radix: 2)
while result.count < 8 {
result = "0" + result
}
						return result;
}
}
// MARK:- Extensible extra functions and methods
// This function is called when the input string is over 100 characters
private func encodeBinaryWhenCharOverlimit(input: String) -> Void {
DispatchQueue.main.async {
var bytes:[UInt8] = []
for char in input.utf8 {
bytes += [char]
}
// Output the result
for n in self.toBinaryStringArray(array: bytes) {
self.resultOutput.text.append(n.inserting(separator: " ", every: 50))
}; sleep(1)
}
}
// MARK:- Binary Encoding algorithm
private func encodeStringBinary(string: String) -> Void {
// var byte = string.utf8.count
var bytes:[UInt8] = []
for char in string.utf8 {
bytes += [char]
}
// Output the result
for x in self.toBinaryStringArray(array: bytes) {
self.resultOutput.text.append(x)
}
}
}
// MARK:- Extensions
extension Collection {
func distance(to index: Index) -> Int { distance(from: startIndex, to: index) }
func subSequences(limitedTo maxLength: Int) -> [SubSequence] {
precondition(maxLength > 0, "groups must be greater than zero")
return .init(sequence(state: startIndex) { start in
guard start < self.endIndex else { return nil }
let end = self.index(start, offsetBy: maxLength, limitedBy: self.endIndex) ?? self.endIndex
defer { start = end }
return self[start..<end]
})
}
var pairs: [SubSequence] { subSequences(limitedTo: 2) }
}
extension StringProtocol where Self: RangeReplaceableCollection {
mutating func insert<S: StringProtocol>(separator: S, every n: Int) {
for index in indices.dropFirst().reversed()
where distance(to: index).isMultiple(of: n) {
insert(contentsOf: separator, at: index)
}
}
func inserting<S: StringProtocol>(separator: S, every n: Int) -> Self {
var string = self
string.insert(separator: separator, every: n)
return string
}
}
I have a button that is supposed auto-detect encoded strings. I have a UISpinner module that allows the user to select the decoding method they want to use. Currently there are three decoding methods: "-- Select decoding --" -> Hexadecimal, Binary, and Base64.
Say the string is in hexadecimal, when the button (for auto-detection) is pressed it calls the hexadecimal string check boolean method and the spinner is supposed to go to the index of 1 (hexadecimal) and when the string is in Binary the binary string check is called and the spinner is supposed to be at index of 2 (binary).
So far, I have two boolean methods that are supposed to check the string using regular expression and return true if the string matches. The problem is, when I give the sub-program a binary string and press the button, it goes to hexadecimal and not binary. Here are the methods I have:
private func isStringHex(source: String) -> Bool {
let reg = try! NSRegularExpression(pattern: "(0x)?([0-9a-f]{16})")
let ran = NSRange(location: 0, length: source.count)
if (reg.firstMatch(in: source, options: [], range: ran) != nil) {
return true
}
return false
}
private func isStringBinary(source: String) -> Bool {
let reg = try! NSRegularExpression(pattern: "([01]{2})")
let ran = NSRange(location: 0, length: source.count)
if (reg.firstMatch(in: source, options: [], range: ran) != nil) {
return true
}
return false
}
This may be a little hard to explain but, for the heck of it I decided to look up code that precisely compares two strings and returns a distance percentage between those strings. Here is the problem: I am trying to take two strings and precisely compare them using precision equality, for example:
String 1 = "Test string"
String 2 = "Test" Now, by precision standards these strings distance from each other would equal to be 50%. I am trying to do that with ALL strings.
The best way I can describe what I am trying to accomplish is: taking two strings and seeing how far away (in distance) they are from each other (like the quoted example). I know that there is a Double method for this in swift called the Jaro Winkler Distance calculation but that is where the problem comes in, I implement the Jaro Winkler solution that I found online into my project but, when I try to compare these two strings:
String 1 = "This is a test string of text - test string"
String 2 = "This is a test string of text - test string" I get that the total distance between those strings is: 93.48837% when in fact, the strings are identical and should give me the resulting distance of 100%. Am I missing something because if I input "Test" into field 1 and "Test" into field two, I get a result of "100%" as the distance comparison output.
Here is the code I found online, it is an extension of string
extension String {
public func distanceJaroWinkler(between target: String) -> Double {
var stringOne = self
var stringTwo = target
if stringOne.count > stringTwo.count {
stringTwo = self
stringOne = target
}
let stringOneCount = stringOne.count
let stringTwoCount = stringTwo.count
if stringOneCount == 0 && stringTwoCount == 0 {
return 1.0
}
let matchingDistance = stringTwoCount / 2
var matchingCharactersCount: Double = 0
var transpositionsCount: Double = 0
var previousPosition = -1
// Count matching characters and transpositions.
for (i, stringOneChar) in stringOne.enumerated() {
for (j, stringTwoChar) in stringTwo.enumerated() {
if max(0, i - matchingDistance)..<min(stringTwoCount, i + matchingDistance) ~= j {
if stringOneChar == stringTwoChar {
matchingCharactersCount += 1
if previousPosition != -1 && j < previousPosition {
transpositionsCount += 1
}
previousPosition = j
break
}
}
}
}
if matchingCharactersCount == 0.0 {
return 0.0
}
// Count common prefix (up to a maximum of 4 characters)
let commonPrefixCount = min(max(Double(self.commonPrefix(with: target).count), 0), 4)
let jaroSimilarity = (matchingCharactersCount / Double(stringOneCount) + matchingCharactersCount / Double(stringTwoCount) + (matchingCharactersCount - transpositionsCount) / matchingCharactersCount) / 3
// Default is 0.1, should never exceed 0.25 (otherwise similarity score could exceed 1.0)
let commonPrefixScalingFactor = 0.1
return jaroSimilarity + commonPrefixCount * commonPrefixScalingFactor * (1 - jaroSimilarity)
}
}
I have one module that is supposed to encode a string to binary and another module that, when passed the encoded binary string, is supposed to to decode that string and print the original string.
In my first module file, I have the encoding process that works. I can pass a regular string of text and the module returns the Binary version of that string, here is the code:
// Returns the byte array value after string value is appended to the resulting string array.
func binaryStringArray(array:[UInt8]) -> [String] {
var res:[String] = []
// Byte in byte array -> append to byte2Binary($e)
for e in array {
let bin = byte2Binary(byte: e)
res.append(bin)
}
// Return the array - raw array print
return res;
}
// Converter - string byte to binary
func byte2Binary(byte:UInt8) -> String {
var result = String(byte, radix: 2)
while result.count < 8 {
result = "0" + result
}
return result;
}
var str:String = "test string"
var bytes:[UInt8] = []
// Iterate through the string characters
for char in str.utf8 {
		//
bytes += [char]
}
// Iterate through the data string array and print the contents of that array
for value in binaryStringArray(array: bytes) {
print(value)
}
// Result output: 01110100 01100101 01110011 01110100 00100000 01110011 01110100 01110010 01101001 01101110 01100111
What I want to do is take the "Result output" pass it as a string in file 2 (decoder) and decode that binary string back to its original string form ("test string").
I am working on a new project, String Converter which will be run on a device supporting iOS 13.0 and up. My problem is in the Tab Layout, specifically the encoder tab I have a UIScrollView (and UIView inside that module) set up and linked as "mainScrollView" in the custom class "FirstViewController.swift".
The outlet for mainScrollView is in the class FirstViewController which is set as the custom class for the Encoder Scene. The mainScrollView (UIScrollView) outlet is set as linked to the UIScrollView module object in that specific scene (Encoder Scene). The link is displayed as set in the "Connection Inspector" under "Outlets" and as said previously that UIScrollView module is in the FirstViewController class.
Despite everything (seemingly) being there, I am still getting this error message (which is displayed when the app terminates and takes me to the AppDelegate.swift file):
Thread 1: Exception: "[<UIViewController 0x7f85ea557bb0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key mainScrollView.