I realize I could declare a global var, such as:
var mySpecialSubClass : MySpecialSubClass?
..and then check if it is defined.
Don't know of any reason to do one way or another, but I was wondering if there was a search for an instance of "MySpecialSubClass" function or method available?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
This question is also, here, one StackOverflow. But it's only gotten 8 views, and I am stuck till I find out what am I doing wrong.
I am able to create a URLSesion, build a request with a file to upload and successfully call it from my app. On my server side, the proper script is called, uploaded file is saved, etc,. However, I am not receiving the HTTP responses, data, etc.
Actually had this working without the delegate, when the HTTP response functions were within the task itself. But am now trying to expand functionality and am missing something while trying implement the delegate.
The trimmed code is below, and it all works, with the exception of setting up UIViewController as the URLSession delegate. Just trying to figure out why my UIViewController is not receiving the HTTP responses.
Below is the code for:
UIViewController
Class which creates the upload session (UploadService)
Extension for UIViewController which I want to use to process the responses
How the previous task looked, when it worked. Before I tried to implement the delegate.
UIViewController
class UploadInv : UIViewController {
var xFile : XFile?
...create UI....
let uploadService = UploadService()
lazy var uploadSession: URLSession = {
let configuration = URLSessionConfiguration.default
return URLSession(configuration: configuration, delegate: self, delegateQueue: .main)
}()
override func viewWillAppear(_ animated: Bool) {
...
}
override func viewDidLoad() {
super.viewDidLoad()
uploadService.uploadSession = uploadSession
... code the lays out all buttons, labels, etc...
}
@objc func buttonAction(sender: UIButton!) {
guard let theButton = sender else { return}
let myTag = theButton.tag
switch myTag {
//button to start upload
case ButtType.up.rawValue:
uploadService.start(upFile: xFile!, script: "uploadOrig.pl", upLoadInvClass: self)
uploadService.task?.resume()
//button to select file to upload
case ButtType.file.rawValue:
... file xFile with file info
}
}
UploadService
class UploadService {
var task: URLSessionUploadTask?
var uploadSession = URLSession.shared
func start(upFile: XFile, script: String, upLoadInvClass: UploadInv) {
var request = upFile.makeUrlReq(upFile: upFile, script: script)
self.task = uploadSession.uploadTask(with: request, from: request.httpBody! )
}
}
extension
extension UploadInv: UIDocumentPickerDelegate, URLSessionDelegate {
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
... file xFile info for upload ....
... http request created ....
}
// Below are the three simple functions which I would handle
// responses the server, but these never seem to get called.
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let err = error {
print("Error: \(err.localizedDescription)")
}
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: (URLSession.ResponseDisposition) -> Void) {
print("didReceive response")
completionHandler(URLSession.ResponseDisposition.allow)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
print("didReceive data")
if let responseText = String(data: data, encoding: .utf8) {
print(responseText)
}
}
}
Pre-Delegate model which worked
class UploadService {
var uploadSession = URLSession.shared
func start(upFile: XFile, script: String, upLoadInvClass: UploadInv) {
var request = upFile.makeUrlReq(upFile: upFile, script: script)
uploadSession.uploadTask(with: request, from: request.httpBody )
{ (data, response, error) in
if let response = response {
upLoadInvClass.upResp(resp: response)
}
if let error = error {
upLoadInvClass.upErr(error: error)
}
if let data = data {
upLoadInvClass.upData(data: data)
}
}.resume()
}
}
_Posted this here, on Stackoverflow. But after 2+ weeks got only 10 views and no responses. _
I have my URLSession delegates working, but am curious about the order I get back response, data, and error.
Right now am testing purposeful errors on my server side, so I can check the response if it's not 200. If it's not, I do not need to process the data, etc.
So I could use a flag, but have to make sure that I'l always get response, data, and error in a specific order?
Does such an order exist?
extension UploadInv: UIDocumentPickerDelegate, URLSessionDataDelegate,URLSessionTaskDelegate, URLSessionDelegate {
// Error received
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let err = error {
print("Error: \(err.localizedDescription)")
}
}
// Response received
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: (URLSession.ResponseDisposition) -> Void) {
completionHandler(URLSession.ResponseDisposition.allow)
DispatchQueue.main.async { [self] in
if let httpResponse = response as? HTTPURLResponse {
if httpResponse.statusCode != 200 {
DispatchQueue.main.async { [self] in
self.myStatus.text = "Error \(String(httpResponse.statusCode))"
myBackButt.isEnabled = true
}
}
}
}
}
// Data received
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
DispatchQueue.main.async { [self] in
Currently I am placing a UITableView inside my UIViewController, with multiple other items. I am not using a UITableViewController.
However I am unable to register the identifier "masterlist", or should I say I am not sure where I can register it. I am not using storyboard, and if I am still to register it in my UIViewController's viewDidLoad, I am unable to figure out the proper syntax.
Is this something I can do?
class BeginNewCustomer: UIViewController {
let myList = createTblView()
override func viewDidLoad() {
super.viewDidLoad()
myList.delegate = self
myList.dataSource = self
}
func createTblView() -> UITableView {
let myTable = MyTableView(frame: CGRect(x: 0, y: 0, width: 0, height: 0 ))
myTable.backgroundColor = .white
return myTable
}
extension BeginNewInv: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dbClass.invsList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
// let cell = tableView.dequeueReusableCell(withIdentifier: "masterlist", for: indexPath)
var config = cell.defaultContentConfiguration()
.... fill the configuration
cell.contentConfiguration = config
return cell
}
}
I am trying to add a UITextView within my app to output data to. Naturally the data will eventually be bigger than the size of the UITextView, and the view is a set size. So I would like the user to be able to scroll through its content.
However, I cannot scroll through the content in the app. Am I supposed to build the scrolling function myself? Seems weird that I would have to do that, but I cannot seem to find the answer to this on the web.
I’ve also noticed that no vertical scroll at shows up when the text count is larger than the size of the object, which makes me wonder if I am
missing a property or two.
func createStatusField() -> UITextView {
let myStatus = UITextView(frame: CGRect(x: 50, y: 50, width: 100, height: 300))
myStatus.autocorrectionType = .no
myStatus.text = "hello there"
myStatus.backgroundColor = .secondarySystemBackground
myStatus.textColor = .secondaryLabel
myStatus.font = UIFont.preferredFont(forTextStyle: .body)
myStatus.layer.zPosition = 1
myStatus.isScrollEnabled = true
myStatus.showsVerticalScrollIndicator = true
return myStatus
}
Is it possible to switch to a new View without using NavigationStack or NavigationLink or NavigationView?
I know I can do it with a Bool, which either shows the second view, or the first, and then toggles the Bool.
But can't I do something like this? Which obviously doesn't work.
struct BasicButton: View {
var buttonLabel = "Create User"
var body: some View {
Button {
CreateUser() //another SwiftUI view, not a function
} label: {
Text(buttonLabel)
}
}
}
Correct me if I'm wrong, but with the latest version of Xcode (15.x) you can no longer add files to the iPhone simulator by dragging them into the the Files app.
I also tried to share the files from my Mac desktop to the simulator. But after selecting the simulator, absolutely nothing happened.
So I had to do it the long way:
Add a folder to the simulator with a unique name, in the Files app
Get the document path, print(URL.documentsDirectory.path())
Back track into the folder structure till I find that folder
cp the files to that folder
Please tell me that there is a way that I haven't found on Google, or that I somehow was doing what the Apple dox suggested, but missed a step.
New to Macs and still learning Swift. My first goal is a game so I actually am looking for TWO recommendations:Is there an advantage to Swift vs. Objective C when programming game apps?Can anyone recommend a decent book for beginners? I'm not a beginner, however my last heavy experience was with Perl, C, and the WindowsSDK. So am behind the times.Thank you
I have the code below which works just fine. getTwinklingGem returns type MyGem.
What I cannot figure out is if there is a proper syntax for writing the NOT into the if statement. Am still too new to Swift.
This works, but seems lengthy:
if let twinkling = getHighGem(), twinkling != nil
Is this the proper way to test for a nil return?
if let twinkling = getHighGem() as? MyGem
if let twinkling = getTwinklingGem() {
print ("not nil")
}
It's a small thing, but every time I open my current Xcode project the default iOS device to run my app on is my phone. Is there a way to change it to one of the simulators? i.e. iPhone Pro 11?
Xcode 13.3
Whenever I hit enter on Xcode, it starts off the new line with an indentation. It doesn't matter if I am creating a new line, or moving lines down, it always start the new line, or the moved line with an indentation.
This happens when I have:
Prefer Indent Using set to Tabs
regardless if I have
Syntax-Aware Indenting: Return checked or unchecked
Any thoughts?
Update, now somehow it does that auto indent on every line no matter whether I set it tabs or spaces. It's as if I broke it. Very annoying, please help!
Am trying to port away from .textLabel.text, as per Apple but I can't seem to find the way to get the text I set.
I now set my cells this way:
let cell = UITableViewCell()
var config = cell.defaultContentConfiguration()
config.text = dbClass.nameList[indexPath.row].clientName
config.textProperties.color = .black
config.textProperties.alignment = .center
cell.contentConfiguration = config
But when I try to get the text of a selected cell (once the user hits the OK button) I can't seem to reverse engineer how to get the text.
let cell = myClientList.cellForRow(at: myInvsList.indexPathForSelectedRow!)
let config = cell?.contentConfiguration
dbClass.curMasterinvList = ?????? (can't find what property to read here
I even tried
let config = cell?.defaultContentConfiguration()
Hoping that the text would be in there, but the text there is blank, so am assuming that's just the standard config before I've changed it.
I have Googled as much as possible, but can't seem to find this very simple need.
Am going through a SwiftUI course, so the code is not my own.
When I migrated my @Bindings into @Published items in an @ObservableObject I started getting the following error:
Publishing changes from within view updates is not allowed, this will cause undefined behavior.
The warning occurs in the ScannerView which is integrated with the main view, BarcodeScannerView. It occurs when an error occurs, and scannerView.alertItem is set to a value.
However, it does not occur when I am setting the value of scannerView.scannedCode, and as far as I can tell, they both come from the sample place, and are the same actions.
There are tons of posts like mine, but I have yet to find an answer. Any thoughts or comments would be very appreciated.
BarcodeScannerView
import SwiftUI
struct BarcodeScannerView: View {
@StateObject var viewModel = BarcodeScannerViewModel()
var body: some View {
NavigationStack {
VStack {
ScannerView(scannedCode: $viewModel.scannedCode, typeScanned: $viewModel.typeScanned, alertItem: $viewModel.alertItem)
.frame(maxWidth: .infinity, maxHeight: 300)
Spacer().frame(height: 60)
BarcodeView(statusText: viewModel.typeScanned)
TextView(statusText: viewModel.statusText, statusTextColor: viewModel.statusTextColor)
}
.navigationTitle("Barcode Scanner")
.alert(item: $viewModel.alertItem) { alertItem in
Alert(title: Text(alertItem.title), message: Text(alertItem.message), dismissButton: alertItem.dismissButton)
}
}
}
}
BarcodeScannerViewModel
import SwiftUI
final class BarcodeScannerViewModel: ObservableObject {
@Published var scannedCode = ""
@Published var typeScanned = "Scanned Barcode"
@Published var alertItem: AlertItem?
var statusText: String {
return scannedCode.isEmpty ? "Not Yet scanned" : scannedCode
}
var statusTextColor: Color {
scannedCode.isEmpty ? .red : .green
}
}
ScannerView
import SwiftUI
struct ScannerView: UIViewControllerRepresentable {
typealias UIViewControllerType = ScannerVC
@Binding var scannedCode : String
@Binding var typeScanned : String
@Binding var alertItem: AlertItem?
func makeCoordinator() -> Coordinator {
Coordinator(scannerView: self)
}
func makeUIViewController(context: Context) -> ScannerVC {
ScannerVC(scannerDelegate: context.coordinator)
}
func updateUIViewController(_ uiViewController: ScannerVC, context: Context) {
}
final class Coordinator: NSObject, ScannerVCDelegate {
private let scannerView: ScannerView
init(scannerView: ScannerView) {
self.scannerView = scannerView
}
func didFind(barcode: String, typeScanned: String) {
scannerView.scannedCode = barcode
scannerView.typeScanned = typeScanned
print (barcode)
}
func didSurface(error: CameraError) {
switch error {
case .invalidDeviceinput:
scannerView.alertItem = AlertContext.invalidDeviceInput
case .invalidScannedValue:
scannerView.alertItem = AlertContext.invalidScannedValue
case .invalidPreviewLayer:
scannerView.alertItem = AlertContext.invalidPreviewLayer
case .invalidStringObject:
scannerView.alertItem = AlertContext.invalidStringObject
}
}
}
}
Haven't touched Xcode since it upgraded to 12.4. Just started a new app, which I planned to create without storyboards. But the default files I am used to deleting or manipulating aren't there anymore. I don't even see AppDelegate.swift.
So did Xcode 12.4 get rid of "storyboards" by default? And if so, where do I go to relearn how to start?
Thanks.
I just upgraded to Xcode 12.4, created a project using the "app" template, without SwiftUI, I chose Storyboard instead.
I placed a small image on the LaunchScreen.storyboard, and an NSLog output in my ViewController.
When I run the app on the simulator, the LaunchScreen does not, show, and I do get my NSLog output. So I know the app is running. When run this bare app on my physical iPhone X...I do get the launch screen.
So I opened a game app I started under Xcode 11.x. It will show the LaunchScreen on both simulator and my device.
I've checked that Launch screen interface file base name is set to LaunchScreen in Info.plist. It's also set under App Icons and Launch Images.
Is this some bug?