With this code, button is at the center of the view and message is logged only when tapping in the button
1. struct ContentView: View {
2. var body: some View {
3.
4. ZStack {
5. Button(action: {
6. print("Touched")
7. }) {
8. Image(systemName: "square.split.diagonal.2x2")
9. .font(.system(size: 24))
10. .foregroundColor(.black)
11. // .position(x: 12, y: 12)
12. }
13.
14. }
15. .frame(width: 300, height: 300)
16. .background(Color.yellow)
17. }
18. }
But if I uncomment line 11, the message is logged on tap anywhere in the view.
How is it position() changes the behaviour ?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I have encountered the following problem with a List.
The setup is as follows
@State private var allItems : [SomeItem]
@State private var selected : SomeItem?
// in the body
List(allItems, $selection) { theItem in …
}
where SomeItem is a struct.
When some properties of an item in allItems changes, the values that I read in theItem are not updated.
Just as if old content was cached.
I changed allItems to a computed var and everything works OK.
I read this SO thread https://stackoverflow.com/questions/74083515/swiftui-list-item-not-updated-if-model-is-wrapped-in-state
but that does not give a full explanation.
So my questions:
Is there effectively an issue here ?
when is it safe to use a State var as the Content of List ?
Is it OK (it seems) if the properties of items do not change ?
It seems also OK if the list of allItems is modified (appended, reduced) without problem changing the properties of its elements.
How to do if needed to change both allItems (append for instance) and change the properties of some items, as computed var cannot be modified.
Hope the question is clear.
I get this error in console in a SwiftUI MacApp on Xcode 15.0.1 and MacOS 14.1.2
FAULT: <NSRemoteView: 0x11f03bc00 com.apple.TextInputUI.xpc.CursorUIViewService TUICursorUIViewService> determined it was necessary to configure <TUINSWindow: 0x11f1b2390> to support remote view vibrancy
I found similar errors that seem to be harmless messages popping up: https://developer.apple.com/forums/thread/72133
No idea what can cause such message, even less how to correct it.
Here is the set up.
I have a UITableViewController (controller 1), to which I get from a controller (0)
As I need to add a searchView atop the tableView, I addSubview to the superview.
This is done in viewWillAppear
self.view.superview?.addSubview(searchView) // AboveTableView
searchView.isHidden = true
print("willAppear", self.view.superview, self.tableView.superview)
It works perfectly well, I get:
willAppear Optional(<UIViewControllerWrapperView: 0x103d2eef0; frame = (0 0; 393 852); autoresize = W+H; layer = <CALayer:
From this VC, I segue to another VC (2) with a show segue and comes back with an unwindSegue to return to (1).
Problem is that no, superviews are nil.
@IBAction func unwindToTableViewController(_ sender: UIStoryboardSegue) {
print("unwind", self.view.superview, self.tableView.superview)
}
gives
unwind nil nil
If I step back from this controller (1) to the controller (0) from which I segued and segue again to the TableViewController (1), everything works as expected.
In addition, if I go from 1 -> 2 by instantiating (2), everything works OK when I unwind to (1).
I know a solution is to refactor code replacing UITableViewController with a UIViewController and embed a TableView inside. But I would like to understand why my present design does not work.
To change the background of a TextField, I simply apply:
TextField("0.0", value: $p, format: .number)
.textFieldStyle(PlainTextFieldStyle())
.background(.red)
That does only work with plain style, but it works.
Trying something similar on a button changes the container view background.
The only solution I've found is to overlap with a Rectangle.
How is it ?
A SwiftUI bug ?
A current limit of Swift ?
A rationale for it ?
There a better solution I've not found ?
I feel a bit dumb now.
I once succeeded to change the language of an app on Watch simulator. So it is possible.
And I'm not able to repeat (fool of me I did not took note of how I did it).
I just remember it was simply through some language settings selection, may be rebooting the Mac, but not by changing anything in code.
Does someone know how to do ?
I have an @objC used for notification.
kTag is an Int constant, fieldBeingEdited is an Int variable.
The following code fails at compilation with error: Command CompileSwift failed with a nonzero exit code if I capture self (I edited code, to have minimal case)
@objc func keyboardDone(_ sender : UIButton) {
DispatchQueue.main.async { [self] () -> Void in
switch fieldBeingEdited {
case kTag : break
default : break
}
}
}
If I explicitly use self, it compiles, even with self captured:
@objc func keyboardDone(_ sender : UIButton) {
DispatchQueue.main.async { [self] () -> Void in
switch fieldBeingEdited { // <<-- no need for self here
case self.kTag : break // <<-- self here
default : break
}
}
}
This compiles as well:
@objc func keyboardDone(_ sender : UIButton) {
DispatchQueue.main.async { () -> Void in
switch self.fieldBeingEdited { // <<-- no need for self here
case self.kTag : break // <<-- self here
default : break
}
}
}
Is it a compiler bug or am I missing something ?
In this app I have a view with 3 textFields or labels on which I have gesture recogniqzers.They work OK.I have localized the app for 2 more languages, and now, when I switxh language (inside the app), I get the following error:2018-02-16 00:19:34.951810+0100 Autonomie[1635:1007703] [Warning] WARNING: A Gesture recognizer (<UITapGestureRecognizer: 0x1757fd90; state = Possible; view = <UITextView 0x17b86600>; target= <(action=autonomieVersionViewTapped:, target=<Autonomie.StartViewController 0x1757f890>)>>) was setup in a storyboard/xib to be added to more than one view (-><UITextView: 0x17ba8000; frame = (60.5 50; 198 25); text = 'version 0.5 © AlphaNums 2...'; clipsToBounds = YES; hidden = YES; opaque = NO; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x175e25d0>; layer = <CALayer: 0x175da320>; contentOffset: {0, 0}; contentSize: {198, 31}>) at a time, this was never allowed, and is now enforced. Beginning with iOS 9.0 it will be put in the first view it is loaded into.<UIButtonLabel: 0x176d3da0; frame = (160 18; 0 0); text = 'Calcular el rango …'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x176d01c0>><UIButtonLabel: 0x1765cc40; frame = (160 18; 0 0); text = 'Calculer autonomie …'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1765cda0>>And gestures do not work.If I switch back to the original language, everything OK.
When compiling this OSX App in XCode 10 beta 2 (Swift 4.2), I get a warning that did not show in XCode 9.4 each time I create an NSConstraint programmaticallyInstance will be immediately deallocated because property 'myConstraint' is 'weak'fileprivate weak var myConstraint : NSLayoutConstraint!
myConstraint = NSLayoutConstraint(item: aButton, attribute: .top, relatedBy: .equal, toItem: aView, attribute: .bottom, multiplier: 1.0, constant: 30)However, there is no such warning for IBOutlet@IBOutlet fileprivate weak var anotherConstraint : NSLayoutConstraint!Is it a just a new warning for an error that existed before ? Or did something change in NSConstraint ?Should I treat IBOutlet and programmatically created differently with respect to weak ?
Learning Widgets, I try a simple pattern: get a textField in the app;
have the Widget updated when textField is changed.
App is UIKit.
Widget has No "included Configuration Intent".
It compiles and works. Widget is updated every 5 minutes as asked line 23 (final snippet).
But the message is never updated (line 48 of final snippet) with globalToPass (as expected from line 24): it always shows "Hello".
What I tried: Create a singleton to hold the data to pass:
class Util {
		
		class var shared : Util {
				struct Singleton {
						static let instance = Util()
				}
				return Singleton.instance;
		}
		
		var globalToPass = "Hello"
}
shared the file between the 2 targets App and WidgetExtension
In VC, update the singleton when textField is changed and ask for widget to reload timeline
		@IBAction func updateMessage(_ sender: UITextField) {
				
				Util.shared.globalToPass = valueToPassLabel.text ?? "--"
				WidgetCenter.shared.reloadTimelines(ofKind: "WidgetForTest")
				WidgetCenter.shared.reloadAllTimelines()
		}
Problem : Widget never updated its message field
Probably I need to have the message in @State var, but I could not get it work.
Here is the full widget code at this time:
import WidgetKit
import SwiftUI
struct LoadStatusProvider: TimelineProvider {
		
		func placeholder(in context: Context) -> SimpleEntry {
				
				SimpleEntry(date: Date(), loadEntry: 0, message: Util.shared.globalToPass)
		}
		func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
				
				let entry = SimpleEntry(date: Date(), loadEntry: 0, message: Util.shared.globalToPass)
				completion(entry)
		}
		func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
				var entries: [SimpleEntry] = []
				// Generate a timeline consisting of five entries an hour apart, starting from the current date.
				let currentDate = Date()
				for minuteOffset in 0 ..< 2 {
						let entryDate = Calendar.current.date(byAdding: .minute, value: 5*minuteOffset, to: currentDate)!
						let entry = SimpleEntry(date: entryDate, loadEntry: minuteOffset, message: Util.shared.globalToPass)
						entries.append(entry)
				}
				let timeline = Timeline(entries: entries, policy: .atEnd)
				completion(timeline)
		}
}
struct SimpleEntry: TimelineEntry {
		let date: Date
		let loadEntry: Int
		let message: String
}
struct WidgetForTestNoIntentEntryView : View {
		var entry: LoadStatusProvider.Entry
		var body: some View {
				let formatter = DateFormatter()
				formatter.timeStyle = .medium
				let dateString = formatter.string(from: entry.date)
				return
						VStack {
								Text(String(entry.message))
								HStack {
										Text("Started")
										Text(entry.date, style: .time)
								}
								HStack {
										Text("Now")
										Text(dateString)
								}
								HStack {
										Text("Loaded")
										Text(String(entry.loadEntry))
								}
						}
		}
}
@main
struct WidgetForTestNoIntent: Widget {
		let kind: String = "WidgetForTestNoIntent"
		var body: some WidgetConfiguration {
				StaticConfiguration(kind: kind, provider: LoadStatusProvider()) { entry in
						WidgetForTestNoIntentEntryView(entry: entry)
				}
				.configurationDisplayName("My Widget")
				.description("This is an example widget.")
		}
}
struct WidgetForTestNoIntent_Previews: PreviewProvider {
		static var previews: some View {
				
				WidgetForTestNoIntentEntryView(entry: SimpleEntry(date: Date(), loadEntry: 0, message: "-"))
						.previewContext(WidgetPreviewContext(family: .systemSmall))
		}
}
I have not defined extension for IntentHandler
From the Landmarks sample project, I tried a variation, to get two cells side by side in the List.
This is the original with on cell per row as in the tutorial:
struct LandmarkList: View {
		
		var body: some View {
				List(landmarks) { landmark in
						LandmarkRow(landmark: landmark)
				}
		}
}
Surprisingly, the following variation works well to display 2 cells side by side:
struct LandmarkList: View {
		
		var body: some View {
				List (0 ..< (landmarks.count+1)/2) { item in
						LandmarkRow(landmark: landmarks[2*item])
						if 2*item + 1 < landmarks.count {
								LandmarkRow(landmark: landmarks[(2*item)+1])
						}
				}
		}
}
I thus tried to go on and add navigationLinks…
It works when adding a navigation link to the first cell only
struct LandmarkList: View {
		
		var body: some View {
				NavigationView {
						List (0 ..< (landmarks.count+1)/2) { item in
								NavigationLink(destination: LandmarkDetail()) {
										LandmarkRow(landmark: landmarks[2*item])
								}
								if 2*item + 1 < landmarks.count {
										LandmarkRow(landmark: landmarks[(2*item)+1])
								}
						}
						.navigationTitle("Landmarks")	
				}
		}
}
But adding NavigationLink to the second makes it fail:
struct LandmarkList: View {
		
		var body: some View {
				NavigationView {
						List (0 ..< (landmarks.count+1)/2) { item in
								NavigationLink(destination: LandmarkDetail()) {
										LandmarkRow(landmark: landmarks[2*item])
								}
								if 2*item + 1 < landmarks.count {
NavigationLink(destination: LandmarkDetail()) {
										 LandmarkRow(landmark: landmarks[(2*item)+1])
								 }
								}
						}
						.navigationTitle("Landmarks")	
				}
		}
}
The error is on line 3:
The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions Is it a normal List behaviour ?
Or did I miss something ?
Which expression could I break ?
I suspect this point has been discussed in length, but I would like to find some reference to the design logic behind some Swift key aspect : the assignment operator, by value or reference.
We know well how = works, depending it deals with reference or value (knowing the consequence of misuse) and the difference between the 2 :
class AClass {
var val: Int = 0
}
struct AStruct {
var val : Int = 0
}
let aClass = AClass()
let bClass = aClass
bClass.val += 10
print("aClass.val", aClass.val, "bClass.val", bClass.val)
let aStruct = AStruct()
var bStruct = aStruct
bStruct.val += 10
print("aStruct.val", aStruct.val, "bStruct.val", bStruct.val)
Hence my question.
Was it ever considered to have 2 operators, one used to assign reference and the other to assign value?
Imagine we have :
= operator when dealing with references
:= operator when dealing with content.
Then
let bClass = aClass
would remain unchanged.
But
var bStruct = aStruct
would not be valid anymore, with a compiler warning to replace by
var bStruct := aStruct
On the other end, we could now write
let bClass := aClass
to create a new instance and assign another instance content, equivalent to convenience initialiser
class AClass {
var val: Int = 0
init(with aVar: AClass) {
self.val = aVar.val
}
init() {
}
}
called as
let cClass = AClass(with: aClass)
But the 2 operators would have made it clear that when using = we copy the reference. When using := we copy content.
I do think there is a strong rationale behind the present design choice (side effects I do not see ?), but I would appreciate to better understand which.
In the new version of download > More, there doesn't seem to be a way to filter search efficiently. I searched for instance for MacOS (to see all releases). I get a very long list (200+) references, with a lot of Xcode, but nothing specific to MacOS.
If I search for Xcode 11, I get all Xcode references:
I added quotes to try and force an exact search, I just get a Java extension…
That was not the case in the previous version of the more page. Or do I miss something ?
I try to rotate a page 180° in a pdf file.
I nearly get it, but the page is also mirrored horizontally.
Some images to illustrate:
Initial page:
Result after rotation (see code): it is rotated 180° BUT mirrored horizontally as well:
The expected result
It is just as if it was rotated 180°, around the x axis of the page. And I would need to rotate 180° around z axis (perpendicular to the page). It is probably the result of
writeContext!.scaleBy(x: 1, y: -1)
I have tried a lot of changes for transform, translate, scale parameters, including removing calls to some of them, to no avail.
@IBAction func createNewPDF(_ sender: UIButton) {
var originalPdfDocument: CGPDFDocument!
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = urls[0]
// read some pdf from bundle for test
if let path = Bundle.main.path(forResource: "Test", ofType: "pdf"), let pdf = CGPDFDocument(URL(fileURLWithPath: path) as CFURL) {
originalPdfDocument = pdf
} else { return }
// create new pdf
let modifiedPdfURL = documentsDirectory.appendingPathComponent("Modified.pdf")
guard let page = originalPdfDocument.page(at: 1) else { return } // Starts at page 1
var mediaBox: CGRect = page.getBoxRect(CGPDFBox.mediaBox) // mediabox which will set the height and width of page
let writeContext = CGContext(modifiedPdfURL as CFURL, mediaBox: &mediaBox, nil) // get the context
var pageRect: CGRect = page.getBoxRect(CGPDFBox.mediaBox) // get the page rect
writeContext!.beginPage(mediaBox: &pageRect)
let m = page.getDrawingTransform(.mediaBox, rect: mediaBox, rotate: 0, preserveAspectRatio: true) // Because of rotate 0, no effect ; changed rotate to 180, then get an empty page
writeContext!.translateBy(x: 0, y: pageRect.size.height)
writeContext!.scaleBy(x: 1, y: -1)
writeContext!.concatenate(m)
writeContext!.clip(to: pageRect)
writeContext!.drawPDFPage(page) // draw content in page
writeContext!.endPage() // end the current page
writeContext!.closePDF()
}
Note: This is a follow up of a previous thread,
https://developer.apple.com/forums/thread/688436
I use UIActivityViewController to airDrop pdfFile (pdfURL) from iPhone to iMac.
Works well, file is airDropped.
let activityVC = UIActivityViewController(activityItems: [pdfURL], applicationActivities: nil)
present(activityVC, animated: true, completion: nil)
I want to customise it:
limit services to AIrDrop and mail
How can I exclude such services as WhatsApp, Notes… ?
perform some action once the file has completed airDrop or once cancelled.
I tried to implement with completionWithItemsHandler:
activityVC.completionWithItemsHandler = { (activity, success, items, error) in
print("Completed")
}
This doesn't work, print is not executed.
My ultimate goal is to close the activityVC automatically once action was completed, without need to tap close button.
Should I define some content for applicationActivities ?