Posts

Post marked as solved
2 Replies
366 Views
the docs are not helpful. in fact they don't seem to be indicating anything that works.so I'm hoping for a code example from someone who has been through this already.the context:I am writing a NSDraggingSource class. supporting the required method :func draggingSession(_ session: NSDraggingSession, sourceOperationMaskFor context: NSDraggingContext) -> NSDragOperation // we would like to respond with move and copy. let response : NSDragOperation = NSDragOperation.copy.rawValue | NSDragOperation.move.rawValue return response } as I noted, I want to provide 2 supported drag types: move, and copy.the docs say to do this:If the source permits dragging operations, the elements in the mask are one or more of the constants described in Obtaining Information About the Dragging Session, combined using the C bitwise OR operator.C Bitwise OR Operator is documented to be "|"Apple does not provide any notable examples of using this in the real world. the few 3rd party examples I have found look like this:let result2 = inputA | inputB print("Result after applying | operator:",result2)/* resultResult after applying | operator: 7 */// note: that example is worthless in this context. I wind up with a cascade of opaque errors with unhelpful suggestions.this is not something that can be guessed. It needs to be documented. it needs to be clear, and have multiple examples. Real ones. Not integers. Barring that tho... has anyone been through this, and can provide a straightforward example?
Posted
by eblu.
Last updated
.
Post not yet marked as solved
4 Replies
358 Views
so I have this challenge that keeps coming up. I solve it each time, but it's messy. I'd like to do it better.my classes derive from a protocol OR a superClass, but in this case it's a protocol.and the reason I have a hierarchy at all is that the classes have to handle different data similarly.so one of the central methods of the class (this is a for instance) is a method that converts the class's internal type to another type.func convert()->Stringa sibling class might need a similar method, but with a different return type:func convert()->Intthese classes are required to have a common ancestor (because their instances will eventually be in the same array.)But, I cannot define the 'convert' method in the protocol or the superclass, such that code addressing as yet unidentified specific type as it's superclass, can simply call the method:let myVar = classInstanceTreatedAsProtocolOrSuperClass.convert()I am instead, forced to do a switch:switch superClassObject{ case is ClassType: let myLet = (superClassObject as! ClassType).convert() whole list of things to do once we get that value case is OtherClassType: all of literally the same code pattern with the potential for slight differences due to type. ...}at times like this, with the Overabundance of required if and if let statements just to get through this, Swift goes from fun, to nightmarishly wordy. I would like to define, in my protocol, a method that defers the return type, but sets up teh method name, so that classes the partake of my protocol, can be expected to support that method. I don't think that's possible in swift. it may conflict with some of the behavior already in place... but I thoought I'd ask. It's no fun writing War and Peace, over and over again.
Posted
by eblu.
Last updated
.
Post not yet marked as solved
3 Replies
1.1k Views
in the tutorial I am following, which is for Swift 4.2 there is code, that when converted to my app's context looks like this:public enum PropertyFamily: String, ClassFamily { case CNStringProp = "CNStringProp" case CNIntProp = "CNIntProp" case CNBoolProp = "CNBoolProp" case CNFloatProp = "CNFloatProp" case CNClampedFloatProp = "CNClampedFloatProp" case CNColor_rgbaProp = "CNColor_rgbaProp" case CNPoint_xyProp = "CNPoint_xyProp" case CNSize_whProp = "CNSize_whProp" case CNSize_whdProp = "CNSize_whdProp" case CNVector_xyzProp = "CNVector_xyzProp" static var discriminator: Discriminator = .type func getType() -> AnyObject.Type { switch self { case .CNStringProp: return CNStringProp.self case .CNIntProp: return CNIntProp.self case .CNBoolProp: return CNBoolProp.self case .CNFloatProp: return CNFloatProp.self case .CNClampedFloatProp: return CNClampedFloatProp.self case .CNColor_rgbaProp: return CNColor_rgbaProp.self case .CNPoint_xyProp: return CNPoint_xyProp.self case .CNSize_whProp: return CNSize_whProp.self case .CNSize_whdProp: return CNSize_whdProp.self case .CNVector_xyzProp: return CNVector_xyzProp.self } } }this is an attempt to support saving Arrays with subclasses of a single class, without steamrolling the class type on load.everything that starts with 'CN' is an NSObject subclass. the goal of the enum is to load a String property and turn it into a class type that can be used per record while loading an array.there is a protocol that defines ClassFamily (supplied by the tutorial):/// To support a new class family, create an enum that conforms to this protocol and contains the different types. protocol ClassFamily: Decodable { /// The discriminator key. static var discriminator: Discriminator { get } /// Returns the class type of the object coresponding to the value. func getType() -> AnyObject.Type } /// Discriminator key enum used to retrieve discriminator fields in JSON payloads. enum Discriminator: String, CodingKey { case type = "type" }I'm learning as I go, but I've hit a snag. I suspect that it's an issue that comes from Swift 4.2 moving to Swift 5on return in the 'getType' function I have an error that states: 'Enum case 'ClassName' cannot be used as an instance member'there is a 'fix it' button. and when that happens,this: return CNSize_whProp.selfturns into this : return PropertyFamily.CNSize_whProp.selfwhich sets off even worse errors:'Cannot convert return expression of type 'PropertyFamily' to return type 'AnyObject.Type''I know the compiler is barking up the wrong tree. What it transforms the code into is gibberish. What I do not know, is what the real problem is. The example is explicit, but it does not go into any detail about how to handle the AnyObject.type type when things go wrong.
Posted
by eblu.
Last updated
.
Post marked as solved
3 Replies
451 Views
I can do this with a Float or a Double, but I'm curious...can I define a new property type?the general idea is to make a new Kind of float that is limited to values > 0 & < 1.creating a normalized float.I could build it as a structure:struct normalizedFloat { var value: Float{ get{return internalValue} set{ internalValue = Float.minimum(Float.maximum(value, 0), 1) } } var internalValue : Float = 0 }but that creates extra work any time a 'normalized float' comes up in the data...var norm : normalizedFloat = normalizedFloat(value : 0.123)instead of : var norm : normalizedFloat = 0.124I have some experience overloading operators, by no means am I an expert at that... but this seems 'next level' compared to that. what kinds of search terms should I use to find out more? is it even possible?
Posted
by eblu.
Last updated
.
Post marked as solved
3 Replies
385 Views
I have a framework. this is the entire thing:import Foundation public let BKNoteChangeAdd : String = "BKNoteChangeAdd" public let BKNoteChangeRemove : String = "BKNoteChangeRemove" public let BKNoteChangeSet : String = "BKNOteChangeSet" public protocol BKNotifier{ func registerForNotes(observer: NSObject) func unregisterForNotes(observer: NSObject) func updateRegisteredObservers(_ key: String, change: [String : [Any]], objectPath : [BKNotifier]) } public protocol BKObserver{ func objectChanged(_ objectPath: [BKNotifier] , key: String, change : [String : [Any]]) }it defines 2 protocols.this framework is built ina different project than the one I am currently working on.I would have rather installed it on the machine and just imported it into my project that way, but there's nothing detailing how to do that, and it's clearly not automatic. So instead, I am adding it to my project.I drag the product from XCode's file list to my current project.(i Have now done this dozens of times)I discovered that a change was necessary in order to get my protocol to work in the new context... registerForNotes and unregisterForNotes' observer property was AnyObject. It is required to be NSObject to work inside of a struct... I can't explain it, I didn't set the limitations... AnyClass doesn't work, But NSObject does. I am not put out by that at all. But, when I made the change in my framework, and recompiled, and deleted and re-dragged, and imported the framework into my new framework...I get error messages that my class does not conform to BKNotifier, here's those two methods:public mutating func registerForNotes(observer: NSObject) { if observer is BKObserver && regObjs.contains(observer) == false{ regObjs.append(observer) } } public mutating func unregisterForNotes(observer: NSObject) { if let anIndex = self.regObjs.firstIndex(of: observer){ self.regObjs.remove(at: anIndex) } }and if I let the editor make stubs for conforming to BKNotifier I get this: public func registerForNotes(observer: AnyObject) { <#code#> } public func unregisterForNotes(observer: AnyObject) { <#code#> }I tried AnyObject precisely 1 time. yet I can completely remove all references to the framework, remove all framework related code, clean the BKNote framework's compile, and recompile, re-do everything... from scratch... and it still throws this error.what else can I try?
Posted
by eblu.
Last updated
.
Post not yet marked as solved
2 Replies
308 Views
I am having some difficulty getting started with this feature.my project is a framework, And It's time to test soem of the things I'm doing in that framework.I saw that I could add a playground to my project, and I thought that was exactly what I needed. I added a new playground to my project, imported my framework, compiled that framework, and nothing works. Is this not what it's meant for? Does it just plain not work like that? or have I missed something?
Posted
by eblu.
Last updated
.
Post not yet marked as solved
7 Replies
617 Views
so... it's impractical and just a bit too much to post the code... it's an entire app, several frameworks, and well... a LOT of code. So I'm hoping for some more general advice on this one.I am getting an error message of : Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional valueat a very wierd spot.on the first case of a switch, where the item being switched is NOT an optional.The property being switched is a String, and I can see it in the debugger: It's not optional and it != nil.I figured I was facing a recursion issue, but I've learned how to recognise them in the debugger, and nope. Not recursion (no irrevocable loop here)Here's what I most recently did to my app: I unembedded a View from a tabView in InterfaceBuilder, and had to re-connect 3 outlets.the error I am getting is specific to making a selection of a model object. (which is the same thing as adding it to an array.) so the error, is not telling me what's going wrong, and it's at a very wierd place that cannot possibly be the issue, and I am at a loss. there's no indication of _any_ optionals at all in this part of the app.
Posted
by eblu.
Last updated
.
Post not yet marked as solved
1 Replies
316 Views
I know this is a long shot. and I've looked at the docs, and it doesn't seem like its a possibility. But I figured I'd ask here just in case I didn't see something important.I have recently added NSNumberFormatter to my workflow, and it works great for most things. There's just one instance where it doesn't seem to have capability.and that's formatting the display of Arrays of numbers.for instance:let arr = [0.0, 3.4, 6.6, 9.99, 124.0]might display as :0.0 - 124.0I have a solution, that works great. but it's an either or proposition. I can't use NSNumber formatter AND my solution. I have to choose. and frankly: NSNumberFormatter is very convenient. So... is there a special class of number formatter that Might be able to handle this kind of Number transform to String? or am I right in assuming that no... number formatters aren't intended to work like that?
Posted
by eblu.
Last updated
.
Post not yet marked as solved
8 Replies
1.2k Views
this happens to be in the context of UserDefaults. I'm trying to track down an issue where a particular class is turned into it's superclass, either when saving to UserDefaults, or loading from UserDefaults.the classes in question (the super class and the class that gets 'permanently coerced') are for all purposes have the same footprint in storage. Same properties. Just different behavior after being loaded. What is saved to UserDefaults is a Data object constructed from an array.the array is defined as an array of the superclass type:var items : [BKLayerController]the saving and the loading code:open var items : [BKLayerController] { get{ var theObjs : [BKLayerController] = [] if let theData = UserDefaults.standard.data(forKey: BKToolboxDefaults) as? Data{ do { theObjs = try PropertyListDecoder().decode([BKLayerController].self, from: theData) } catch { debugPrint(error) } } return theObjs } set{ do { let theData = try PropertyListEncoder().encode(newValue) UserDefaults.standard.set(theData, forKey: BKToolboxDefaults) } catch { debugPrint(error) } } }the Defaults registration code: let layer = BKLayerController() layer.name = "layer" let textLayer = BKTextLayerCon() textLayer.name = "textLayer" do { let theData = try PropertyListEncoder().encode([layer,textLayer]) UserDefaults.standard.register(defaults: [BKToolboxDefaults : theData ]) } catch { }the class "BKTextLayerCon"is a "BKLayerController" class (it's super class) upon loading of the Defaults. It may happen during the saving process, I still haven't figured out how to test that yet.my question, is that when you load objects with the propertyListDecoder (and with Codable Decoders in general) do you need to specify specific types? If so, what would that look like? like this?if let theData = UserDefaults.standard.data(forKey: BKToolboxDefaults) as? Data{ do { theObjs = try PropertyListDecoder().decode([[BKLayerController].self, [BKTextLayerCon].self], from: theData) } catch { debugPrint(error) } }
Posted
by eblu.
Last updated
.
Post not yet marked as solved
2 Replies
734 Views
so this is a bit of a poser, I can do it without using filter, but I'd like to explore the possibilities.consider an array of arrays :var array01 : [String] = ["one","two","three","four","bob","mary","adam","cecil","lambert","fitswidget","oar","twelve"] var array02 : [String] = ["one","two","three","four","marley","dee","sevil","pour","cdc","astec","plar","been"] var array03 : [String] = ["one","two","three","four","rent","on","gret","jesus","wonder","see","mixed","****"] var array04 : [String] = ["one","two","three","four","gidget","oops","fentonil","john","cerci","may","pole","gouge"] var array05 : [String] = ["one","two","three","four"] var glomArray = [array01, array02, array03, array04, array05]the goal is to get an array of elements that are common to all o fthe subArrays.we can get a flat map of the glomArray:let fmap = glomArray.flatMap({$0})then we can count how many times each element of array01 shows up in the fmap array (no code because it's fairly obvious)I was wondering if I could do this with a filter. and what I came up with won't work. But could it work?var hitArray = array01.filter({ fmap.filter({$0 == $0}).count == 5 })what I'm trying to do is filter array01, and count how many times it shows up in fmap. if the element shows up 5 times, the evaluation is true, and that element is included in the array. I could easily write a test function, that would evaluate that. What I'm nterested in here, is whether or not it is possible to perform this calulation with a filter, embedded inside another filter?
Posted
by eblu.
Last updated
.
Post not yet marked as solved
16 Replies
3.3k Views
the documentation abruptly ends where my questions begin.I have a mac os X document app. please refer to this if your experience is in IOS, it most likely will not be of very much help.Background:I am currently trying to adopt Codable, very much against my better instincts, because a number of subsystems in the Mac OS have been fairly recently uncerimoniously kicked down a flight of stairs when NSCoding was damaged. I backed into the knowlege that NSCoding no longer worked for custom classes. The system returns nil, on decoding these classes. Then I got neck deep in a mess trying to implement NSSecureCoding, which went precisely nowhere.Anyway, If I want to continue working on any aspect of my app, I need to get archiving working. NSCoding, and NSSecureCoding don't work. The only other option is Codable. This is not the time to take my fledgling app and cut it's head off and try to graft a new on on it... But I have no choice.the issue:public struct BKColorComponents: Codable{ public var red : CGFloat = 1.0 public var green : CGFloat = 1.0 public var blue : CGFloat = 1.0 public var alpha : CGFloat = 1.0 }by all accounts of online tutorials and the byzantine documentation from Apple HQ, this struct is now Codable compliant.except that it crashes the file save. Here's that code in context:open var components : BKColorComponents = BKColorComponents() enum CodingKeys: String, CodingKey { case components } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(components, forKey: .components) }my document class saving method:override func data(ofType typeName: String) throws -> Data { return try PropertyListEncoder().encode(docData) }there's not much documentation about how to do that at all. I'm not fond of the PropertyListEncoder, but whatever. I'm following along with someone's tutorial, because Apple has dropped the ball in a major way on the subject of archives and serialization. Believe me, I'd rather look up the answer than ask in the forums, I tried. The most important thing about this is that it serializes, and it runs through a host of other objects before it hits this structure, and they all encode without complaint. But for some reason, as soon as this struct comes up, the app crashes.there's no errors, no red flags of any kinds.I just get this error during a save (which seems to take about 10 times longer than it should):Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffeef3fff50)thoughts appreciated.
Posted
by eblu.
Last updated
.
Post not yet marked as solved
14 Replies
2.3k Views
I can't figure it out.mac os, Swift 5, Cocoa, drag n drop, NSPasteboardfirst, this is not an NSCoding issue. It's an NSPasteboard issue. Which is gratuitously backwards. it may be related, but NSPasteboardWritable is different enough to be punishing all the way through, and similar enough to remind you all the way that it doesn't need to be this horrible.my class supports the PasteboardWriting protocol.public func pasteboardPropertyList(forType type: NSPasteboard.PasteboardType) -> Any?{ let coder = NSKeyedArchiver(requiringSecureCoding: false) // whatever. secure is fine. //coder. coder.encode(name, forKey: "name") // these work as expected. coder.encode(hint, forKey: "hint") coder.encode(selectedMode, forKey: "selectedMode") // this is where the problem starts coder.encode(modes, forKey: "modes") // this one too. coder.encode(baseMode, forKey: "baseMode") // and this one as well. coder.encode(delegate, forKey:"delegate") // at the moment, this IS nil coder.encode(rep, forKey: "rep") // this is also nil coder.encode(subCons, forKey:"subCons") // and this is an empty array. coder.finishEncoding() let theData = coder.encodedData return theData }the properties : selectedMode, baseMode, and modes are all NSCoding compliant classes. In modes case, it's an array of the same class as baseMode and selectedMode. I have stepped through the code. They definetly get encoded.then on decoding the coder reports that there is indeed an entry for the key, and proceeds to produce a nil value for it.public required init?(pasteboardPropertyList propertyList: Any, ofType type: NSPasteboard.PasteboardType) { super.init() do { let decoder = try NSKeyedUnarchiver(forReadingFrom: propertyList as! Data) self.name = decoder.decodeObject(forKey: "name") as! String self.hint = decoder.decodeObject(forKey: "hint") as! String if decoder.containsValue(forKey: "selectedMode"){ self.selectedMode = (decoder.decodeObject(forKey: "selectedMode") as? BKLayConMode) // this always returns,and it returns a nil } if decoder.containsValue(forKey: "baseMode"){ if let b = (decoder.decodeObject(forKey: "baseMode") as? BKLayConMode){ self.baseMode = b } } self.modes = (decoder.decodeObject(forKey: "modes") as! [BKLayConMode]) if decoder.containsValue(forKey: "rep"){ self.rep = (decoder.decodeObject(forKey: "rep") as? NSObject) } if decoder.containsValue(forKey: "delegate"){ self.delegate = (decoder.decodeObject(forKey:"delegate") as? BKLayConDelegate) } self.subCons = (decoder.decodeObject(forKey: "subCons") as! [BKLayerController]) // now we set it up. self.createLayer() for each in self.subCons{ each.registerForNotes(observer: self) self.layer.addSublayer(each.layer) } if self.selectedMode != nil{ self.selectedMode.registerForNotes(observer: self) } self.baseMode.registerForNotes(observer: self) } catch { debugPrint("i screwed up the drag n drop pasteboard reading for BKLayerController.") } }I use conditional tests (which I WOULD comment, but the cursor no longer goes where I put it) to test for "selectedMode" "baseMode" and "modes" the archive Has those values set. It just returns nil for every one of them, and my NSCoding initWithCoder method (in the property's class) never gets called. I don't want to be making my own NSKeyedArchiver, and doing all this myself. It's brutally difficult, punitive, gratuitously different, and required. You can't properly support drag n drop without making your own NSKeyedArchiver, and individually archiving the properties of the Object you need to drag. There's no other way. (Codable is out of bounds at the moment, so please... don;t even mention it) I think I have done everything correctly here. There's certainly no docs, examples or tutorials that cover this subject. Anyone with experience that can see an obvious problem?
Posted
by eblu.
Last updated
.