Post

Replies

Boosts

Views

Activity

Rotating a page in a pdf file - and get a mirrored image
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
2
0
1.8k
Aug ’21
Search in Download / more broken ?
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 ?
2
0
574
Jul ’21
Getting back from Splitview
In this app, I have: a VC as entry point (root) which segues (push) to a SplitViewController On iPad, when I get into the splitView, I can get back to the root by dragging down the split view. But on iPhone, this does not work: even though presentation is .automatic, Splitview covers all screen. No way to get back. I tried to create a back button in the detail views… Could not get it. What is the best way to do this ? is there a setup for the initial segue or the views presentation modes to allow pop back ? can I add a back button ? Where, calling what action to return ? I cannot embed splitViewController in nav stack … I would like to have the same solution on both iPhone and iPad…
1
0
569
Jun ’21
Lines numbering in Code Block
The Code Block doesn't number lines anymore. The work around is to ask for Numbered list in addition to Code block. Just applying Code Block: required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) commonInit() } Code Block AND Numbered List (or the other order) 1. required init?(coder aDecoder: NSCoder) { 2. super.init(coder: aDecoder) 3. commonInit() 4. } Is there another way to get numbering directly ?
4
0
817
Jun ’21
Sandbox - security scoped URL - MacOS
In a MacOS App: When I create a file (in a folder), I save a security bookmark for the file. if I ask user to authorise its folder (before creating the file in it), I can save its bookmark too, allowing to create other files in this folder. So, when I create a file and need to create a companion (eg, a Results file), I first ask access to the folder, then create the file and create the results file in the same folder (hence having sandbox authorisation). My understanding is that it is not possible to programmatically create and save the folder bookmark, after deriving its url from the file url, without requesting user to explicitly grant access (with NSOpen panel) ? Which would be very logical as it would deny the goal of security bookmarks. So, is user explicit authorisation required (logical but creates more complexity when user moves files in the Finder). Note: In fact don't really need it, as I save bookmark for every accessed file, but I would like to know.
1
0
730
Apr ’21
Distribution of MacApp outside of Appstore for a demo version
I consider the following distribution scheme for some Mac App: distribute the commercial (paying) version on Appstore propose a free demo version (of course limited in some aspects) on a web site. This would of course be notarised. The reason is to avoid having several versions on the Appstore which could create some confusion. The 2 versions would have similar names and differ essentially in the size of data they can handle. Does anyone know if this is authorised by the Appstore Guidelines ? Or must I publish both on the AppStore ? Is there a risk my app being rejected as spam ?
1
0
498
Apr ’21
Assignment operator in Swift - What is the rationale behind language design ?
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.
2
0
667
Mar ’21
Uppercased words are not spoken correctly
Using AVSpeechSynthesizer, I noticed that some works in UPPERCASe are not correctly spoken. SMALL is pronounced small but WIDTH is pronounced W-I-D-T-H I reproduced the problem in playground: let sentence = "Hello everyone. Two minutes to go. SMALL WIDTH." let synthesizer = AVSpeechSynthesizer() let utterance = AVSpeechUtterance(string: sentence) utterance.voice = AVSpeechSynthesisVoice( 	language: "en-GB" ) utterance.rate = AVSpeechUtteranceDefaultSpeechRate * 1.05 synthesizer.speak(utterance) Is it the expected behaviour ?
1
0
1.1k
Jan ’21
List with 2 cells side by side
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 { &#9;&#9; &#9;&#9;var body: some View { &#9;&#9;&#9;&#9;List(landmarks) { landmark in &#9;&#9;&#9;&#9;&#9;&#9;LandmarkRow(landmark: landmark) &#9;&#9;&#9;&#9;} &#9;&#9;} } Surprisingly, the following variation works well to display 2 cells side by side: struct LandmarkList: View { &#9;&#9; &#9;&#9;var body: some View { &#9;&#9;&#9;&#9;List (0 ..< (landmarks.count+1)/2) { item in &#9;&#9;&#9;&#9;&#9;&#9;LandmarkRow(landmark: landmarks[2*item]) &#9;&#9;&#9;&#9;&#9;&#9;if 2*item + 1 < landmarks.count { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;LandmarkRow(landmark: landmarks[(2*item)+1]) &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;} &#9;&#9;} } I thus tried to go on and add navigationLinks… It works when adding a navigation link to the first cell only struct LandmarkList: View { &#9;&#9; &#9;&#9;var body: some View { &#9;&#9;&#9;&#9;NavigationView { &#9;&#9;&#9;&#9;&#9;&#9;List (0 ..< (landmarks.count+1)/2) { item in &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;NavigationLink(destination: LandmarkDetail()) { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;LandmarkRow(landmark: landmarks[2*item]) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;if 2*item + 1 < landmarks.count { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;LandmarkRow(landmark: landmarks[(2*item)+1]) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;.navigationTitle("Landmarks")&#9; &#9;&#9;&#9;&#9;} &#9;&#9;} } But adding NavigationLink to the second makes it fail: struct LandmarkList: View { &#9;&#9; &#9;&#9;var body: some View { &#9;&#9;&#9;&#9;NavigationView { &#9;&#9;&#9;&#9;&#9;&#9;List (0 ..< (landmarks.count+1)/2) { item in &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;NavigationLink(destination: LandmarkDetail()) { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;LandmarkRow(landmark: landmarks[2*item]) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;if 2*item + 1 < landmarks.count { NavigationLink(destination: LandmarkDetail()) { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; LandmarkRow(landmark: landmarks[(2*item)+1]) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; } &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;.navigationTitle("Landmarks")&#9; &#9;&#9;&#9;&#9;} &#9;&#9;} } 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 ?
2
0
604
Dec ’20
Passing data from an App VC to its widget
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 { &#9;&#9; &#9;&#9;class var shared : Util { &#9;&#9;&#9;&#9;struct Singleton { &#9;&#9;&#9;&#9;&#9;&#9;static let instance = Util() &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;return Singleton.instance; &#9;&#9;} &#9;&#9; &#9;&#9;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 &#9;&#9;@IBAction func updateMessage(_ sender: UITextField) { &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;Util.shared.globalToPass = valueToPassLabel.text ?? "--" &#9;&#9;&#9;&#9;WidgetCenter.shared.reloadTimelines(ofKind: "WidgetForTest") &#9;&#9;&#9;&#9;WidgetCenter.shared.reloadAllTimelines() &#9;&#9;} 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 { &#9;&#9; &#9;&#9;func placeholder(in context: Context) -> SimpleEntry { &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;SimpleEntry(date: Date(), loadEntry: 0, message: Util.shared.globalToPass) &#9;&#9;} &#9;&#9;func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) { &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;let entry = SimpleEntry(date: Date(), loadEntry: 0, message: Util.shared.globalToPass) &#9;&#9;&#9;&#9;completion(entry) &#9;&#9;} &#9;&#9;func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) { &#9;&#9;&#9;&#9;var entries: [SimpleEntry] = [] &#9;&#9;&#9;&#9;// Generate a timeline consisting of five entries an hour apart, starting from the current date. &#9;&#9;&#9;&#9;let currentDate = Date() &#9;&#9;&#9;&#9;for minuteOffset in 0 ..< 2 { &#9;&#9;&#9;&#9;&#9;&#9;let entryDate = Calendar.current.date(byAdding: .minute, value: 5*minuteOffset, to: currentDate)! &#9;&#9;&#9;&#9;&#9;&#9;let entry = SimpleEntry(date: entryDate, loadEntry: minuteOffset, message: Util.shared.globalToPass) &#9;&#9;&#9;&#9;&#9;&#9;entries.append(entry) &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;let timeline = Timeline(entries: entries, policy: .atEnd) &#9;&#9;&#9;&#9;completion(timeline) &#9;&#9;} } struct SimpleEntry: TimelineEntry { &#9;&#9;let date: Date &#9;&#9;let loadEntry: Int &#9;&#9;let message: String } struct WidgetForTestNoIntentEntryView : View { &#9;&#9;var entry: LoadStatusProvider.Entry &#9;&#9;var body: some View { &#9;&#9;&#9;&#9;let formatter = DateFormatter() &#9;&#9;&#9;&#9;formatter.timeStyle = .medium &#9;&#9;&#9;&#9;let dateString = formatter.string(from: entry.date) &#9;&#9;&#9;&#9;return &#9;&#9;&#9;&#9;&#9;&#9;VStack { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;Text(String(entry.message)) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;HStack { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;Text("Started") &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;Text(entry.date, style: .time) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;HStack { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;Text("Now") &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;Text(dateString) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;HStack { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;Text("Loaded") &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;Text(String(entry.loadEntry)) &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;} } @main struct WidgetForTestNoIntent: Widget { &#9;&#9;let kind: String = "WidgetForTestNoIntent" &#9;&#9;var body: some WidgetConfiguration { &#9;&#9;&#9;&#9;StaticConfiguration(kind: kind, provider: LoadStatusProvider()) { entry in &#9;&#9;&#9;&#9;&#9;&#9;WidgetForTestNoIntentEntryView(entry: entry) &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;.configurationDisplayName("My Widget") &#9;&#9;&#9;&#9;.description("This is an example widget.") &#9;&#9;} } struct WidgetForTestNoIntent_Previews: PreviewProvider { &#9;&#9;static var previews: some View { &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;WidgetForTestNoIntentEntryView(entry: SimpleEntry(date: Date(), loadEntry: 0, message: "-")) &#9;&#9;&#9;&#9;&#9;&#9;.previewContext(WidgetPreviewContext(family: .systemSmall)) &#9;&#9;} } I have not defined extension for IntentHandler
2
0
2.1k
Dec ’20
Cannot activate Xcode Edit>Substitution menu
When editing a Swift file in Xcode 12.2, I wanted to change the quotes autocompletion. For this I looked at the Edit > Substitution menu and selected smartQuotes. From this point, the whole substitution menu is disabled, no way to enable back. Opened another file: same issue. Opened another older version of Xcode: the same. Opened Xcode 12.2 on another Mac: same thing How can I re-enable the menu ? Whilst typing this message, I tried again and the menu is once again reactivated ! I did nothing (at least intentionally). Was it some type of time out or time required to complete a task ? But did not return to normal on the other Mac. But now, 10 more minutes later, it is disabled once again… That's the type of surprise effect I do dislike in an app…
1
0
617
Dec ’20