I juste made a basic project with the Hello World Content View, and it runs on the iPhone
Post
Replies
Boosts
Views
Activity
I can send it with pleasure, by mail because code is very dense, but I think I found what was wrong:
Apple says about @FocusState:
A property wrapper type that can read and write a value that SwiftUI updates as the placement of focus within the scene changes.
to use this FocusState property, I used an enum declaration which was contained in the main view. But if I want to make a TextfieldWithError view, which use this enum, I have to declare this enum alone, not in my main View:
enum LoginFocusable: Hashable {
case email
case pwd
case none
var string: String {
switch self {
case .email: return "email"
case .pwd: return "pwd"
default: return ""
}
}
var nextToVerif: LoginFocusable {
switch self {
case .email: return .pwd
case .pwd: return .email
default: return .none
}
}
}
that's the first point
So, in TextfieldInError, I can have the declaration:
struct TextFieldWithError: View {
var label: String
@Binding var text: String
@Binding var textError: String
@FocusState.Binding var focus: LoginFocusable?
}
But t's not enough, because I will need to use the .focused modifier in TextFieldWithError so, I have to declare another property in TextFieldWithError: focusId of type LoginFocusable, so I will be able to user the .focused modifier
So my code will be
struct TextFieldWithError: View {
var label: String
@Binding var text: String
@Binding var textError: String
var focusId: LoginFocusable?
@FocusState.Binding var focus: LoginFocusable?
var body: some View {
TextField(label, text: $text)
.modifier(TextFieldStyle())
.focused($focus, equals: focusId)
Text(textError)
.foregroundColor(.red)
.frame(height: textError == "" ? 0 : 20)
}
}
Now, in the main view, I can declare:
TextFieldWithError(label: "Email", text: $email, textError: $emailError, focusId: .email, focus: $checkoutInFocus)
Of course, the logic of focus handle has to be written in this main View
I'm not sure the system deletes the file, immediately, because after downloading it, I use Quicklook to preview this file, and it works.
and in the procedure where AlamoFire is called, there are thse lines:
if request.parameters.keys.contains("destination") {
let dest = "file://\(request.parameters["destination"]!)"
documentsURL = URL(string: dest.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)
}
and I fixed the destination parameter to .DocumentDirectory
But After all you're right: I will ask the question to Alamofire developpers
Thank's
I download the file with Alamofire:
public func downloadFile(request: BaseRequest, progressIndicator: UIProgressView?, completion: @escaping(NetworkResult<String, NSString>) -> Void) {
if let progressIndicator = progressIndicator {
progressIndicator.isHidden = false
progressIndicator.progress = 0
}
if let filename = request.parameters["filename"], let displayName = request.parameters["displayname"], let url = URL(string: filename.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!) {
let destination: DownloadRequest.Destination = { _, _ in
var documentsURL: URL!
if request.parameters.keys.contains("destination") {
let dest = "file://\(request.parameters["destination"]!)"
documentsURL = URL(string: dest.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)
} else {
documentsURL = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask)[0]
documentsURL.appendPathComponent(displayName)
documentsURL = URL(string: filename.replacingOccurrences(of: "file://", with: "").addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)
documentsURL = URL(string: filename.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)
}
return (documentsURL, [.removePreviousFile])
}
AF.download(url, to: destination)
.downloadProgress(queue: .main, closure: { (progress) in
if let progressIndicator = progressIndicator {
DispatchQueue.main.async {
progressIndicator.progress = Float(progress.fractionCompleted)
}
}
})
.responseData {
response in
progressIndicator?.isHidden = true
switch response.result {
case .failure(let error):
completion(NetworkResult.failure(NSString(string: error.errorDescription!)))
case .success(_):
completion(NetworkResult.success(response.fileURL?.path ?? ""))
}
}
} else {
completion(NetworkResult.failure(NSString(string: "Impossible de récupérer le fichier, requête \(request)")))
}
}
It would be great if you can send me an example, because I don't understand how to move the view up without a scrollView
Thank's, I will try this
In this case yes, because the value return by resignFirstResponder depends on the call to the function verif()
if I replace the function verif in a synchron function which calls a closure: like this
public func verif(_ completion: @escaping(VerifResult<NSString>) -> Void) {
if obligatoire && text == "" {
print("Echec")
completion(.failure("Zone obligatoire"))
} else {
// make call to a webserver and return .sucess or .failure
print("OK")
completion(.success)
}
}
and I use DispatchGroup in the resignFirstResponder function, like this:
override func resignFirstResponder() -> Bool {
var bRes = false
let group = DispatchGroup()
group.enter()
print("group entered")
verif({
result in
switch result {
case .success: bRes = true
case .failure:
bRes = false
print("Echec")
}
group.leave()
})
group.wait()
print("Groupe libéré")
return bRes
}
it seems to work: resignFirstResponder calls async functions and finish only when these functions are called.
What do you think?
I found a solution, but it implies subclassing the subviews for which the "realSize" is needed : in the method layoutSubviews of a subclassed UIView, the size is correct
I tried all: ViewDidLyoutSubviews, viewWillLayoutSubviews and ViewWillTransaition
there is two problems in viewDidLayoutSubviews:
When the controller appears, viewDidLayoutSubviews is called twice. The sizes of the subviews are not always correct in the first call, it became correct in the second call
when the iphone change its orientation, viewDidLayoutSubviews is called again, but the sizes of the subviews are identical, like if constraints will be applied later. for instance if the width of a subview is 246 in portrait and 278 in landscape : when the controller is in portrait, size is effectively 246. When it turn's to landscape, size is still 246 and when it turns back to portrait, size is 278
Your ,last comment gave me an idea Claude. if I have 2 differnt storyboard for my UITableViewCell, I can write this in the
tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
of the uiViewController:
let cell : UITableViewCell
if view.traitCollection.className == "RR" {
if UIScreen.main.bounds.size.width < UIScreen.main.bounds.size.height{
cell = table.getCell(indexPath) as! class1
} else {
cell = table.getCell(indexPath) as! class2
}
}
where class2 is a descendant of class1
Class2 if a descendant of class1, and can have other UIView installed and as class1 and class2 don't have the same storyboard, the constraints wh-ill not be the same.
I have to precise that I wrote the following extension;
extension UITraitCollection {
public var className: String {
get {
return (horizontalSizeClass == .compact ? "C" : "R") + (verticalSizeClass == .compact ? "C" : "R")
}
}
}
Yes, I thought of something like this
But it means that I have to make constraints programatically for class RR, without capable of using functionallities of IB
Thank's Claude
I'm very sorry, but it seems that file:///Users/patricerapaport/Library/Containers/PR.medical/Data/Documents/ links to file:///Users/patricerapaport/Library/Containers/medical/Data/Documents/
because I wrote this:
let dialogURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
print(dialogURL)
var isDir = ObjCBool(false)
let exists = FileManager.default.fileExists(atPath: dialogURL!.path, isDirectory: &isDir)
print(exists)
and the result for print(exists) is true
(I don't know how to close the thread)
I thought it was something like that, but it means that if I don't correct the size in size inspector, I will always have the problem.
IB can deserialise values by reading XIB file, but there is no way to change these values by program and serialise them back.
The case I presented was very simple, but what if I put constraints by program? In this case I don't know the exact size of MyView and if I have multiple subclassed controls, it becomes very confuse in the view of Interface Builder.