preselectedAssetIdentifiers for iOS 14 - swift

I have a function like:
func presentPhotoLibrary() {
let photoLibrary = PHPhotoLibrary.shared()
if PHPhotoLibrary.authorizationStatus(for: .readWrite) == .authorized {
var config = PHPickerConfiguration(photoLibrary: photoLibrary)
config.selectionLimit = 0
let phPicker = PHPickerViewController(configuration: config)
phPicker.delegate = self
present(phPicker, animated: true)
}
}
I also have a collection view that the user can select images from.
When the picker is presented, I want the selected images from the collection view to be shown as selected in the photo library picker. This function is achievable by PHPickerConfiguration 's preselectedAssetIdentifiers for iOS 15. However, I'm trying to have the same behaviour for iOS 14.
Any ideas?

Related

How to connect to an external display using iOS13 Swift or SwiftUI

Maybe a bit of a newbie here, so forgive me if the an easy fix, but I have used the below code pre ios13 to display a image on an external display, but now Ive come across a warning.
The warning is 'Setter for 'screen' was deprecated in iOS 13.0'
MY CODE:
#objc func setupScreen(){
if UIScreen.screens.count > 1{
//find the second screen
let secondScreen = UIScreen.screens[1]
secondScreen.overscanCompensation = .none
//set up a window for the screen using the screens pixel dimensions
secondWindow = UIWindow(frame: secondScreen.bounds)
//windows require a root view controller
let viewcontroller = UIViewController()
secondWindow?.rootViewController = viewcontroller
//tell the window which screen to use
secondWindow?.screen = secondScreen
//set the dimensions for the view for the external screen so it fills the screen
secondScreenView = UIView(frame: secondWindow!.frame)
//add the view to the second screens window
secondWindow?.addSubview(secondScreenView!)
//unhide the window
secondWindow?.isHidden = false
//customised the view
let img = UIImage(named: "chart.png")
// view.layer.contents = img?.cgImage
secondScreenView?.layer.contents = img?.cgImage
// secondScreenView!.backgroundColor = UIColor(patternImage: UIImage(named: "chart.png")!)
secondScreenView!.addSubview(externalLabel)
}
}
#objc func screenDisconnected(){
secondWindow = nil
secondScreenView = nil
}
func registerForScreenNotifications(){
NotificationCenter.default.addObserver(self, selector: #selector(testPatterns.setupScreen), name: UIScreen.didConnectNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(testPatterns.screenDisconnected), name: UIScreen.didDisconnectNotification, object: nil)
}
}
I tried looking in the Apple documentation but I can't find anything?
Any help would be great.
P.S it does still work but would like to get rid of the warning.
cheers!

Accessing NSWindow-like properties in Catalyst macOS app

I am thinking about porting my macOS app to Catalyst.
My app shows a transparent window (no title bar, clear background) on top of all other apps windows (dock included).
To do that, in the non-catalyst code I use:
window.isOpaque = false
window.hasShadow = false
window.backgroundColor = .clear
window.styleMask = .borderless
window.isMovableByWindowBackground = true
window.level = .statusBar
Using UIKit, I was only able to remove the toolbar so far:
window.titleBar.titleVisibility
...But no clue about the other settings.
I plan to make the app available on the App Store in the future, but if the only way to do so is and hack with a private API, that's fine.
Any ideas?
Thanks in advance
There is no official API for doing that, but you can easily access the NSWindow instance and modify it directly. You can do that manually or using some library like Dynamic (Full disclosure: I'm the author):
let window = Dynamic.NSApplication.sharedApplication.delegate.hostWindowForUIWindow(uiWindow)
window.isOpaque = false
window.hasShadow = false
window.backgroundColor = Dynamic.NSColor.clearColor
window.styleMask = 0 /*borderless*/
window.isMovableByWindowBackground = true
window.level = 25 /*statusBar*/
I have some success removing the close button on Catalyst by calling a function from the viewDidAppear(). I called it AppDelegate().disableTitleBarButtons(). Has to be from view did appear.
AppDelegate().disableTitleBarButtons() is as follows
func disableTitleBarButtons() {
func bitSet(_ bits: [Int]) -> UInt {
return bits.reduce(0) { $0 | (1 << $1) }
}
func property(_ property: String, object: NSObject, set: [Int], clear: [Int]) {
if let value = object.value(forKey: property) as? UInt {
object.setValue((value & ~bitSet(clear)) | bitSet(set), forKey: property)
}
}
// disable full-screen button
if let NSApplication = NSClassFromString("NSApplication") as? NSObject.Type,
let sharedApplication = NSApplication.value(forKeyPath: "sharedApplication") as? NSObject,
let windows = sharedApplication.value(forKeyPath: "windows") as? [NSObject]
{
for window in windows {
let resizable = 4
property("styleMask", object: window, set: [], clear: [resizable])
let fullScreenPrimary = 7
let fullScreenAuxiliary = 8
let fullScreenNone = 9
property("collectionBehavior", object: window, set: [fullScreenNone], clear: [fullScreenPrimary, fullScreenAuxiliary])
}
}
}
Where is says let resizable = 4,
Change to 3 for no Maximise,
Change to 2 for No minimise,
Change to 1 of No Close button.
Play with the other numbers or stylemask settings also. Good luck

Add 'PageSetupAccessory' to PrintPanel for PDFDocument

I have an app which displays a PDFView, and I want it to print the PDF file from the view. Also, I want the Print panel to show the Page Setup Accessory (i.e. the Paper Size, Orientation and Scale settings, like in Preview, which appear as one panel of the drop-down list of options).
Currently, I'm mistakenly printing the PDFView, not the PDF document itself. This only gives me one page and includes the scrollbars in the print-out! I can't see how to init an NSPrintOperation referencing a PDFDocument rather than the PDFView.
Here's my code, which works, but isn't what I want. I presume I'll have to override either the printDocument or printOperation functions of NSDocument with similar code that defines the Panel and the Info.
func thePrintInfo() -> NSPrintInfo {
let thePrintInfo = NSPrintInfo()
thePrintInfo.horizontalPagination = .automatic // Tried fit
thePrintInfo.verticalPagination = .automatic // Tried fit
thePrintInfo.isHorizontallyCentered = true // Tried false
thePrintInfo.isVerticallyCentered = true // Tried false
thePrintInfo.leftMargin = 0.0
thePrintInfo.rightMargin = 0.0
thePrintInfo.topMargin = 0.0
thePrintInfo.bottomMargin = 0.0
thePrintInfo.jobDisposition = .spool
return thePrintInfo
}
// Need to show the 'Page Setup' Options as an Accessory
// e.g. Paper size, orientation.
#IBAction func printContent(_ sender: Any) {
let printOperation = NSPrintOperation(view: thePDFView, printInfo: thePrintInfo())
let printPanel = NSPrintPanel()
printPanel.options = [
NSPrintPanel.Options.showsCopies,
NSPrintPanel.Options.showsPrintSelection,
NSPrintPanel.Options.showsPageSetupAccessory,
NSPrintPanel.Options.showsPreview
]
printOperation.printPanel = printPanel
printOperation.run()
}
Based on #Willeke's comments, I've come up with the following, which seems to work well. (Minor quibble is that the Print dialog isn't a sheet.) If anyone has any improvements, please post a better answer.
#IBAction func printContent(_ sender: Any) {
let printOperation = thePDFView.document?.printOperation(for: thePrintInfo(), scalingMode: .pageScaleNone, autoRotate: true)
printOperation?.printPanel = thePrintPanel()
printOperation?.run()
}

Using UserDefaults in viewWillAppear

I'm setting up the Settings page (in SettingsView class) where users can set «On» / «Off» for the background parallax effect. The selection is saved in UserDefaults().string(forKey: "parallaxStatus"). In the viewWillAppear of ViewController class, I checked the parallaxStatus. If the status of the parallax effect is «On», then this effect is displayed. If the status is «Off», then nothing should happen.
The problem appeared when parallaxStatus changed from «On» to «Off» In this case, the parallax effect still displayed before I reload the View. But if parallaxStatus changed from «Off» to «On», the function works well without reloading the View.
Bellow is the code of viewWillAppear function. Thanks for any help or hint.
override func viewWillAppear(_ animated: Bool) {
let parallaxStatus = UserDefaults().string(forKey: "parallaxStatus")
if parallaxStatus == "On" {
let min = CGFloat(-40)
let max = CGFloat(40)
let xMotion = UIInterpolatingMotionEffect(keyPath: "layer.transform.translation.x", type: .tiltAlongHorizontalAxis)
xMotion.minimumRelativeValue = min
xMotion.maximumRelativeValue = max
let yMotion = UIInterpolatingMotionEffect(keyPath: "layer.transform.translation.y", type: .tiltAlongVerticalAxis)
yMotion.minimumRelativeValue = min
yMotion.maximumRelativeValue = max
let motionEffectGroup = UIMotionEffectGroup()
motionEffectGroup.motionEffects = [xMotion,yMotion]
bgImage.addMotionEffect(motionEffectGroup) } else { }
}
1- You should use a bool value in userDefaults
UserDefaults.standard.bool(forKey: "parallaxStatusOn") // default is false
2- viewWillAppear is called when you dimiss a presented / poped vc so in your case , you use a settingsView not vc verify it's being called by other KVO or any event driven notifier
3- if the state is on and changed to off , verify you remove the motion effects with if the vc is still appeared ( not deallocated btw do it in else of check )
bgImage.motionEffects.forEach { bgImage.removeMotionEffect($0) }

gesture recognizer issue with tic tac toe in xcode

hello there i am trying to figure out what the issue is why i cant get a cross on the game board when a tap is made. the TTT class is the one below the first code and it is called in the main code. i will appreciate if some can help me on this
#IBOutlet var fields: [TTTImageView]!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func fieldTapped (recognizer:UITapGestureRecognizer) {
let tappedField = recognizer.view as! TTTImageView
tappedField.setPlayer(_player: "x.png")
}
func setupField () {
for index in 0 ... fields.count - 1 {
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(fieldTapped))
gestureRecognizer.numberOfTapsRequired = 1
fields[index].addGestureRecognizer(gestureRecognizer)
}
}
import UIKit
class TTTImageView: UIImageView {
var player:String?
var activated:Bool! = false
func setPlayer (_player:String) {
self.player = _player
if activated == false {
if _player == "x.png" {
self.image = UIImage (named: "x.png")
}else{
self.image = UIImage (named: "o.png")
}
activated = true
}
}
}
Make sure when you set fields[index].addGestureRecognizer(gestureRecognizer) to set isUserInteractionEnabled to true.
fields[index].isUserInteractionEnabled = true
Whenever you want to detect user activity (e.g. UITapGestureRecognizer on a UIImageView, you need to set this to true
EDIT:
I also wanted to mention something I noticed after looking at your code again: the method you are using for selectors has been deprecated. If you are using Swift 3 (which I highly recommend you do), you shouldn't call selectors like this: "functionName:" anymore. Now we use selectors like so: #selector(functionName(_:)). You should start updating your code to the most current syntax sooner rather than later.