Post not yet marked as solved
Hi,
I'm trying to convert the following code snippet to Swift:
NSURL* pathURL = [NSURL fileURLWithPath:path];
BOOL success = [pathURL setResourceValue:tags forKey:NSURLTagNamesKey error:&outError];
However, it looks like the equivalent is now blocked in the API definition - in the Xcode 12 Swift API declaration .tagNames (and allValues) are get-only properties of URLResourceValues (according to StackOverflow, they were mutable in the past).
extension URL {
func setTagNames(_ tags: [String] ) {
var values = URLResourceValues()
values.tagNames = tags // Error here: Cannot assign to property: tagNames is get-only
try self.setResourceValues( values )
}
}
How can I set the tagNames?
Thanks,
Thomas
Post not yet marked as solved
Hi,I tried to imeplement some data clustering and separation algorithms with an Xcode playground - however I can't figure out how to create programmatically subfolders in *~/Documents/Shared Playground Data* as FileManager is not availabe in the playground. Any ideas? Thanks, Thomas
Post not yet marked as solved
Hi,I need to resolve a bunch of PHAssets for localIdentifiers from a CoreData database with a mostly in iCloud stored Photos library.Unfortunately on iOS 13 I don't receive all PHAssets when I try to fetch them and I don't receive any additional PHAssets via photoLibraryDidChange.For me it looks like a regression from iOS 12 / Xcode 10 SDK builds where I didn't have that issue so reproducible.When I leave the view controller and then fetch the remaining identifiers again a bit later I get another batch - usually 3 - more but usually not all of them. What do I need to do to resolve all identifiers?Code is similar to:class MyViewController {
private var unresolvedAssets = [String: DCAsset]()
private var resolveAssetsResult : PHFetchResult? = nil
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
PHPhotoLibrary.shared().register(self)
}
deinit {
PHPhotoLibrary.shared().unregisterChangeObserver(self)
}
var lesson: DCLesson! {
didSet {
unresolvedAssets.removeAll()
for asset in lesson.assets {
if asset.localAsset == nil {
unresolvedAssets[instance.localIdentifier] = asset
}
}
let identifiers = unresolvedAssets.keys.map{ return $0 }
print("\(#function) resolving \(unresolvedAssets.count) assets: \(identifiers)")
guard !unresolvedAssets.isEmpty else {
return
}
let options = PHFetchOptions()
resolveAssetsResult = PHAsset.fetchAssets(withLocalIdentifiers:identifiers, options: options)
updateUnresolvedAssets( resolveAssetsResult! )
}
}
func photoLibraryDidChange(_ changeInstance: PHChange) {
DispatchQueue.main.sync {
if let request = resolveAssetsResult,
let changeDetails = changeInstance.changeDetails(for: request) {
print( "Received changes: \(changeDetails.insertedObjects)" )
updateUnresolvedAssets( changeDetails.fetchResultAfterChanges )
}
}
}
private func updateUnresolvedAssets( _ fetchResult: PHFetchResult ) {
fetchResult.enumerateObjects{
phAsset, _, _ in
if let dcAsset = self.unresolvedAssets[phAsset.localIdentifier] {
print("setting localAsset for \(dcAsset.assetIdentifier!)")
dcAsset.localAsset = phAsset
self.unresolvedAssets[phAsset.localIdentifier] = nil
}
}
}
}The following partially logs the resultlesson resolving 9 assets: ["7412823B-7CFB-4538-B380-4F1DCE861A50/L0/001", "3DC75596-22E7-4EAA-A92B-8301C3BB41B6/L0/001", "F6211272-CE49-47BE-9181-31ABF65E737D/L0/001", "C9EC1F1F-AE7E-440A-877A-B37AEE59C1A3/L0/001", "83736D97-94D4-417D-B537-E5C9B1B7BC67/L0/001", "9671C852-8777-4B44-BCF9-F5AFB6C5F8C3/L0/001", "B8EA862B-9B91-4F30-ABC5-82132E848DEA/L0/001", "4287A790-E0E7-494C-B047-7080CDF0E0B9/L0/001", "99C1EF0C-8F31-40C5-8D4A-999280D29739/L0/001"]setting localAsset for 2018-06-22T15:02:25Z-140setting localAsset for 2018-06-22T14:55:26Z-17setting localAsset for 2018-06-22T15:05:13Z-28*** Navigate back and forthlesson resolving 6 assets: ["83736D97-94D4-417D-B537-E5C9B1B7BC67/L0/001", "084B2FBF-17F3-4520-ACD7-BCBFC3E74F0D/L0/001", "C60C84E8-E472-47FF-ADA3-DBAB82804792/L0/001", "3DC75596-22E7-4EAA-A92B-8301C3BB41B6/L0/001", "9671C852-8777-4B44-BCF9-F5AFB6C5F8C3/L0/001", "6EB5B8A7-92A3-4E18-AC7C-A86619CFEFF5/L0/001"]setting localAsset for 2018-06-22T14:55:45Z-11setting localAsset for 2018-06-22T14:54:53Z-9setting localAsset for 2018-06-22T14:55:06Z-17Received changes: []*** Navigate back and forthlesson resolving 3 assets: ["9671C852-8777-4B44-BCF9-F5AFB6C5F8C3/L0/001", "83736D97-94D4-417D-B537-E5C9B1B7BC67/L0/001", "287EBB67-BBBA-4FB9-AEAC-AC0ABD5A9132/L0/001"]setting localAsset for 2018-06-22T14:57:32Z-36
Post not yet marked as solved
Hi,I'm trying to debug an Swift 4.2 executable on an device with iOS 13.1 with Xcode 11.2.1.I`m hitting an local breakpoint and the try to *po* the local variable.It is shown on the left variable pane (without an value) and the name gets completed in the debugger console with tab.However I get the error messagepo assetsByIdentifier
error: <EXPR>:3:1: error: use of unresolved identifier 'assetsByIdentifier'
assetsByIdentifier
^~~~~~~~~~~~~~~~~~What can I check / do?
Post not yet marked as solved
Hi!Hope this is the right forum but I don't see anything more appropriate for ImageCaptureCore related questions.Has anybody got PTPIP camera access working on Mojave? Finally Bonjour advertized cameras are visible again in the Image Capture application, but I don't receive an connection on the listener.The implementation I have- works fine in macOS < 10.10,- on 10.11 the connection stalls after reading the camera date property- on 10.12 and 10.13 an advertized bonjour service is not displayed- on 10.14 it is displayed again but I don't see any connect to my listenerMinimal aample to reproduce in a macOS playground - when you- open ImageCapture.app,- select "shared devies", - expand- select the "Sample Server",you should see two messages with "New state:..." in the console (== Socket connection establishment). import Foundation
import Network
import PlaygroundSupport
class PTPIPProtocolHandler {
private var commandPacketsToSend = [Data]()
private var commandConnection : NWConnection! = nil
private var eventPacketsToSend = [Data]()
private var eventConnection : NWConnection! = nil
func readHeader(connection: NWConnection) {
// Read exactly the length of the header
let headerLength: Int = 12
connection.receive(minimumIncompleteLength: headerLength, maximumLength: headerLength)
{ (content, contentContext, isComplete, error) in
Swift.print( "Received: \(content) error:\(error)" )
if let error = error {
//
} else {
// Parse out body length
var length = 0
var type = 0
var dataPhaseInfo = 0
content!.withUnsafeBytes() {
(p: UnsafePointer<UInt32>) in
length = Int( UInt32( littleEndian:p[0] ) )
type = Int( UInt32( littleEndian:p[1] ) )
dataPhaseInfo = Int( UInt32( littleEndian:p[2] ) )
}
self.readPacket(connection, type:type, length: length)
}
}
}
func readPacket( _ connection: NWConnection, type: Int, length: Int ) {
connection.receive(minimumIncompleteLength: length, maximumLength: length)
{ (content, contentContext, isComplete, error) in
Swift.print( "Received data: \(content) error:\(error)" )
if let error = error {
//
} else {
self.handle( connection, data: content!, type: type )
}
}
}
func handle( _ connection: NWConnection, data: Data, type: Int ) {
}
}
class PTPIPDevice : PTPIPProtocolHandler {
let deviceName : String
let bonjour : NWListener!
let listenerQueue = DispatchQueue( label: "PTPIP Discovery" )
let newConnectionQueue = DispatchQueue( label: "PTPIP connectiom queue" )
private override init() {
preconditionFailure( "Need an device name" )
}
init?( name: String ) {
deviceName = name
var tcpOptions = NWProtocolTCP.Options()
let tcpParameters = NWParameters(tls:nil, tcp:tcpOptions )
tcpParameters.prohibitExpensivePaths = true
// tcpParameters.prohibitedInterfaceTypes = [.cellular, .loopback, .wifi]
tcpParameters.requiredInterfaceType = .wiredEthernet
if let port = NWEndpoint.Port( rawValue: 15740 ) {
bonjour = try? NWListener(using: tcpParameters, on: port )
} else {
bonjour = try? NWListener(using: .tcp )
}
guard let listener = bonjour else {
return nil
}
super.init()
// Advertise a Bonjour service
listener.service = NWListener.Service(name:name, type: "_ptp._tcp.")
listener.newConnectionHandler = {
(newConnection) in
Swift.print( "New connection! \(newConnection.endpoint)" )
// Handle inbound connections
newConnection.stateUpdateHandler = {
[weak self] state in
// .. handle state transitions
print( "New State: \(state)")
}
newConnection.start( queue: self.newConnectionQueue )
self.readHeader(connection: newConnection )
}
listener.stateUpdateHandler = {
state in
Swift.print( "New listener state \(state)" )
}
listener.start( queue: listenerQueue )
}
}
let device = PTPIPDevice( name:"Sample Server" )
PlaygroundPage.current.needsIndefiniteExecution = true
Post not yet marked as solved
Hi,I*m trying to restrict Bonjour advertising to some interfaces - ideally IPv4 on en0.However, regardless how I configure the NWListener, I get all interfaces and ports advertised:
let tcpOptions = NWProtocolTCP.Options()
let tcpParameters = NWParameters(tls:nil, tcp:tcpOptions )
tcpParameters.prohibitExpensivePaths = true
// Has no effect
// tcpParameters.prohibitedInterfaceTypes = [.cellular, .loopback, .wifi]
tcpParameters.requiredInterfaceType = .wiredEthernet // no effect either
if let port = NWEndpoint.Port( rawValue: 15740 ) {
bonjour = try? NWListener(using: tcpParameters, on: port )
} else {
bonjour = try? NWListener(using: .tcp )
}
// Advertise a Bonjour service
listener.service = NWListener.Service(name:name, type: "_ptp._tcp.")How can I advertize only one or two interfaces?