I have an interesting challenge, but I do not know where to start.
given an NSTextView in an NSScrollView, and enough text in the textView to enable scrolling, how do you determine the location of a single word, and jump to it?
we see this sort of behavior in Find panels in Most text editors. So it can be done.
additionally, I would very much like to find some kind of predetermined... elements in the text. as a link or an image is not text but can be inline with the text (in Attributed strings) I would like to put an element in the text that is not text, but is targetable and capable of being tagged with some kind of reference. Almost like a bookmark, in which I can scroll to. I have determined that I could use URL Links. But they are so fragile.
Post
Replies
Boosts
Views
Activity
I have a Mac doc based app.
I have save methods setup (they sort of work... I'm trying to get them up and running)
I'm using NSSecureCoding, with NSObjects in Swift. It has been unusually frustrating.
I have run into something I find wildly difficult to even explain.
I can save a new document that has not been saved yet. it loads as expected.
but if I make a change to a doc I have already saved, and save that, ny file gets wiped out. my save code is called, and the app wipes all of the data out of the saved file. The file exists, but it's emptied.
it goes from around ~200k in size to 2k in size.
there's no error that I have identified. It just wipes my file. So I have NO idea if it's something I did.
docs are... unhelpful. internet searches... are unhelpful.
this is just one of a number of errors I have to figure out, but it is massively complicating everything else.
any ideas welcome.
I have a doc, xib based project.
it has an NSCollectionView, which properly displays the data. including items and section headers.
I have drag n drop enabled where I can drop into the collectionView, and I generate a new object. this is NOT a reordering issue (yet)
when I drop into the collectionView, if the drop is on top of a HeaderView, the drop is canceled (before it gets to my delegate code.) But more importantly : the Header views are entirely ignored in every step of the drag and drop. the hinting, only ever shows up adjacent to a collectionViewItemView, Never below or above the section header. The drop ALWAYS has a section of zero in its index path. regardless of where the drop is.
I tried to override this behavior in both the validate drop and accept drop methods. with a great deal of frustration and struggle I discovered that I cannot compare the placement of my header views, because the frames of those views are all at the base origin point.
is this normal behavior? Has anyone else run into this? is there a fix?
new to Metal,
following Janie Clayton's book. Ran into a problem creating a proper Perspective Projection Matrix.
I'm hoping someone with matrix experience will see this and the issue will jump out.
the matrix structures:
swift:
struct Matrix4x4{
var X : SIMD4<Float>
var Y : SIMD4<Float>
var Z : SIMD4<Float>
var W : SIMD4<Float>
metal:
float4x4 projectionMatrix;
the swift code that generates the projection matrix:
static func perspectiveProjection(_ aspect : Float32, fieldOfView: Float32, near: Float32, far: Float32)->Matrix4x4{
var mat = Matrix4x4()
let zRange = far - near
let fovRadians = fieldOfView * Float32(Double.pi / 180.0)
let yScale = 1 / tan(fovRadians * 0.5)
let xScale = yScale / aspect
let zScale = -( far + near) / zRange
let wzScale = -2 * far * near / zRange
mat.X.x = xScale
mat.Y.y = yScale
mat.Z.z = zScale
mat.Z.w = -1
mat.W.z = wzScale
mat.W.w = 0
return mat
}
how the shader applies the projection matrix :
outVertex.position = uniforms.projectionMatrix * props.modelMatrix * vert[vid].position;
the result here is just the clear color.
it seems that the issue is with wZScale. hard coding that to zero and the mat.W.w to 1.0, allows me to at least see my scene, skewed. messing around with those values, it seems like the objects are crushed and pushed through the camera, existing behind it.
I'm basically dead in the water here, typing word for word what is in the book. it's pretty darned frustrating. I'm just learning my way around matrices.
Hey. I've combed through the seriously weak documentation, looked for examples (none of which are in Swift) I found an Obj-C example and converted it. It doesn't work. It creates an empty hierarchy of SCNNodes. What is going on here? this is the third time, I've written SCNGeometry code from scratch, using examples from different sources, trying to follow the insanely arcane, undocumented, and openGL-ish design pattern. This time, I've taken Obj-C code, and simply converted it, leaving everything as close to the original as possible.what is going on?// BKPivotNode is a subclass of SCNNode. func genTubeTest(aPivot: BKPivotNode)->SCNNode{ var retNode = SCNNode() if aPivot.children.isEmpty != true{ for aChild in aPivot.childNodes{ if let bChild = aChild as? BKPivotNode { let sources = [SCNGeometrySource(vertices: [ SCNVector3(x: -1.0, y: -1.0, z: 0), SCNVector3(x: -1.0, y: 1.0, z: 0), SCNVector3(x: 1.0, y: 1.0, z: 0), SCNVector3(x: 1.0, y: -1.0, z: 0)], count: 4 ), SCNGeometrySource(normals: [ SCNVector3(x: 0.0, y: 0.0, z: -1.0), SCNVector3(x: 0.0, y: 0.0, z: -1.0), SCNVector3(x: 0.0, y: 0.0, z: -1.0), SCNVector3(x: 0.0, y: 0.0, z: -1.0)], count: 4 ), SCNGeometrySource(textureCoordinates: [ CGPoint(x: 0.0, y: 0.0), CGPoint(x: 0.0, y: 1.0), CGPoint(x: 1.0, y: 1.0), CGPoint(x: 1.0, y: 0.0)], count: 4 )] let newElement = SCNGeometryElement(data: NSData(bytes: [0, 2, 3,0,1,2], length: sizeof(Int)), primitiveType: .Triangles, primitiveCount: 2, bytesPerIndex: sizeof(Int)) let newGeo = SCNGeometry(sources:sources, elements:[newElement]) let newMat = SCNMaterial() newMat.diffuse.contents = NSColor.redColor() newMat.transparency = 0.5 newMat.doubleSided = true newGeo.firstMaterial = newMat; let newNode = SCNNode() newNode.geometry = newGeo retNode.addChildNode(newNode) } } } return retNode }
this is super frustrating.I have a class, it's one of hundreds.eariler today, it worked fine. I have made no changes. The editor seems to think I have overriden the superClass's method. (you can find that out by just doing it again and looking at the error messages)But, when I compile. my override is never called. In the OTHER subclasses it is called. I have cleaned and recompiled the entire project. I have re-written the method from scratch. I have copied the method from the super class, and pasted it into the subclass, adding the "override" key word.this is not the first time this has happened.
Hi, caught in a loop of unhelpful error messages. Been trying to find a code example to follow, apparently that is not a thing anymore. the docs... for over 20 years now are only half finished. So Im here in the forums looking for guidance.
I am trying to set a resource for an existing file URL. the intention is to add a tag to the file. Nothing onerous. Should be easy. Getting the list of tags WAS easy.
here's the code as I have it:
func setItemTags(atURL:URL, tags: [String]){
do {
try atURL.setResourceValue(tags, forKey: .tagNamesKey)
} catch let error as NSError {
print(error)
}
}
I get an error that says:
Argument type '[String]' expected to be an instance of a class or class-constrained type
ok. seems pretty straight forward, the Array (which is what I get from acquiring the resources... so this doesn't make much sense at all, but whatever.) needs to be a class. clearly it's a Holdover from Obj-c. And it needs to be an NSArray. I SHOULD be able to bridge to an NSArray by replacing 'tags' with 'NSArray(array: tags)'
but that doesn't work at all. I get a different error.
'setResourceValue(:forKey:)' is unavailable: Use struct URLResourceValues and URL.setResourceValues(:) instead
So no error message is really telling us anything. no matter how much I try, I can't just materialize the answer out of thin air.
what I really need is a single example of how to properly use the 'steresourceValue' function of URL, to set the .tagNamesKey. I am astonished that this is not documented anywhere.*
*I have found ancient examples of this, which is now deprecated by changes to swift, and is only useful as a source of confusion.
Ok, maybe I'm hung up on Mac OS X design patterns, just tell me if that's the case.the problem:I need to draw a line on an existing CGImage.There's no LockFocus methods for CGImage, There's no obvious documented way to get the already created Context of a Bitmap in the CGImage. There's no obvious or explicit code explaining the procedure.I have the reference to the image, I have the two points that make up the line, I know all of the code to draw that line... I just cannot make the context associated to that image, the current context. What gives? what is the design pattern? Please tell me where I can read about this.
I have hit a brick wall. I cannot explain the behavior I am seeing. What it boils down to is: SIMD2<Float> is incompatible with float2.
I am working through tutorials trying to get a handle on Metal. All the tutorials are woefully out of date, so no answers there. But I did find somewhere that I should be using SIMD4<Float> for my point data. Great. I was able to bridge that gap. but I added uv maps using a float2. and the result was a portion of my vertex data gets lost somewhere. The buffer is smaller, by about 25%.
and I cannot figure it out. help?
in anticipation of pertinent questions:
the vertex struct:
struct vertex {
var position : SIMD4<Float> = SIMD4<Float>(x: 0.0,y: 0.0,z: 0.0,w: 0.0)
var uv : SIMD2<Float> = SIMD2<Float>(x:0.0 ,y:0.0)
init(x: Float ,y: Float, z: Float) {
self.position.x = x
self.position.y = y
self.position.z = z
self.position.w = 1.0
uv = SIMD2<Float>(0.5 ,0.5)
}
init( x: Float, y: Float, z: Float, u: Float, v: Float ){
position = SIMD4<Float>(x,y,z,1.0)
uv = SIMD2<Float>(u ,v)
}
}
if I change the SIMD2 to an SIMD4... the entire thing works.
how I measure the size of my buffer:
let matrixSize = MemoryLayout.size(ofValue:vertexField.vertices[0])
let vertsSize = vertexField.vertices.count * matrixSize
// now we make the vertex buffers.
for i in 0..<maxFramesInFlight{
if let aVertBuff = device.makeBuffer(bytes: vertexField.vertices, length: vertsSize, options: .storageModeManaged){
aVertBuff.label = "verts buffer \(i)"
vertexBuffs += [aVertBuff]
}
}
vertexField is a struct containing an array of vertices, and an array of offsets and lengths for the various meshes I make from those vertices. Eventually I'll figure out the elegant way of doing that.
the buffer winds up having 64 elements, out of 84. The fragment shader, assumes 84 entries, and winds up setting those values to 0,0,0,0 0,0.
I sent a single SIMD2<Float> variable to the Fragment shader, and examined it. It was correct.
any ideas are welcome. I am up the river without a paddle on this one.
I have a very simple split view window. everything is laid out, but auot layout is screwing everything up.wish i knew why auto layout jacknifes my Ui.the splitview is the top level view in the window. it is horizontal, and there is a text field in the rightmost view in the splitview.the splitview is tied to the window top, bottom, trailing and leading.at that point, everything works as expected. when compiled, the split controls work just fine.the problem, is when I try to add constraints to the text box. I put top, leading and trailing constraints on. all to superview. IB actually reversed the first item and the second item in the top constraint, thought I caught the issue. But alas, nope. When I run the app, the splitview became a piece of crap. The split control allows you to drag it, but when you let go, it snaps to some point that it won't let go. It will not under any circumstances behave like a splitview any more. There is no justification, there is no reason, there is no logical argument for this kind of behavior. But now I need to dig through the documentation and try to understand the short comings of the autolayout engine. Ideas welcome.
I'm fit to be tied, so I apologise for any harsh language.I have an NSCoding compliant class hierarchy (mac os + swift)And I am adding support for drag n drop.This requires adding NSPasteboardReading/NSPasteboardWritingwhich has been an abysmal experience. I got it working, but not correctly. Now I'm trying to do it right. And something that SHOULD just work, in the context of doing this work is failing to produce expected results. I've already spent too much time trying to guess what the ---- is going on.upon completion of my drop, the source object is asked to provide a "propertyList." I used to encode my entire object and then in the init(withPasteboard) method I would copy the values from the instantiated resulting object to self. Which is a stupid and horrible way of doing the work, But at the time: after 2 weeks of literally trying random things with the pasteboard (lack of examples and documentation) was the only thing that worked.Now, I am encoding the properties of the object, which includes 2 arrays of custom objects (which are both NSCoding compliant, and have been observed correctly encoding and decoding thousands of times.)so it looks like this: func pasteboardPropertyList(forType type: NSPasteboard.PasteboardType) -> Any? {
do {
let archiver = NSKeyedArchiver(requiringSecureCoding: false)
archiver.encode(name, forKey: "name")
archiver.encode(self.type, forKey: "type")
archiver.encode(children, forKey: "children")
// the problem is channels as follows:
archiver.encode(channels, forKey: "channels")
archiver.finishEncoding()
let data = archiver.encodedData
return data
} catch {
//debugPrint("archiveFailed for drag of node in toolbox")
}
return nil
} required init?(pasteboardPropertyList propertyList: Any, ofType type: NSPasteboard.PasteboardType) {
super.init()
if let data = propertyList as? Data{
do {
//let newObject = try NSKeyedUnarchiver.unarchivedObject(ofClass: docDataObj.self, from: data)
let unarchiver = try NSKeyedUnarchiver.init(forReadingFrom: data)
self.name = unarchiver.decodeObject(forKey: "name" ) as! String
self.type = unarchiver.decodeObject(forKey: "type" ) as! String
if unarchiver.containsValue(forKey: "channels"){
let anObj = unarchiver.decodeObject(forKey: "channels" )
if anObj != nil{
if let objTest = anObj as? [docDataChannel]{
self.channels = objTest
}
}
}
if unarchiver.containsValue(forKey: "chidlren"){
self.children = unarchiver.decodeObject(forKey: "children" ) as! [docDataObj]
}
} catch {
//debugPrint("initing from property list failed trying to unarchive")
}
}
}you'll notice a little cottage industry popping up around the property "channels"That's where I always recieve a nil value from the unarchiver. I tried unarchiving every single type (Bool, Double, Float...) that unarchiver supports. There's nothing to unarchive for that key.But I set it. With classes that easily archive elsewhere. I have followed the debugger, and the encode method is called on the contents of the channels array. As far as can be told, the objects are encoded.AND the unarchiver reports that there is a value for that key. every single time. it returns true.the children array... that's empty in my testing, but there IS a value for THAT key.so the unarchiver swears it has a value that it doesn't, that I can confirm is set. what gives?
I have a plugin architecture... the plugins are glorified bundles.
They are compiled at runtime, and embedded in the Main Application Bundle's Plugin folder.
I have hit the point where I need to load the plugins, and query them for data, from inside one of the plugins.
this is usually accomplished in the main bundle with a class :
import Foundation
import CNPlugin
class CNPluginMan{
var plugins : [CNPlugin] = []
init() {
loadPlugins()
}
func loadPlugins(){
do {
let files = try FileManager.default.contentsOfDirectory(at: Bundle.main.builtInPlugInsURL!, includingPropertiesForKeys: nil)
for URL in files{
let aBundle = Bundle(url: URL)
if let als = aBundle?.principalClass{
if let cls = als as? CNPlugin.Type{
let plugin = cls.init()
plugins.append(plugin)
}
}
}
} catch {
print(error)
}
}
}
but Now I am acutely aware that I can't just get the main bundle.
is there a correct way, to get the Host Application's Bundle from a plugin?
using this:
https://developer.apple.com/documentation/metal/modern_rendering_with_metal
I have tried downloading and building several times. Ever since I installed the W5700X the project builds, runs, and only loads the lights, but not the model.
what gives? There's no bugs, it just doesn't load the "bistro" file.
I have a number of objects that handle Drops, all of their code is descended from a single object where I noticed an oddity in Drag n drop behavior. That that is, if I do not add a particular set of lines to the performDrop method, the pasteboard appears to be empty.
what gives?
open override func performDragOperation(_ sender: NSDraggingInfo, forCon: BKLayerController) -> Bool{
var retVal = false
let paneRec = forCon.rep as! CNPanelRecord
		 let pasteBoard : NSPasteboard = sender.draggingPasteboard
		if pasteBoard.types?.contains(CNDragTypeToolBox) == true{
					 retVal = true
					 let encoder = JSONEncoder()
					 let thePoint = CGPoint()
/* if I do not add this if statement... drag n drop does not work */
					 if let newPlistData = pasteBoard.propertyList(forType: CNDragTypeToolBox){}
		let payload = pasteBoard.readObjects(forClasses: [pBoardNode.self], options: nil)
					let droppedItems : [CNDagObj] = (payload as! [pBoardNode]).map({$0.docNode.dagObjs}).flatMap { $0 }
					for each in droppedItems{
							each.uuid = UUID().uuidString
											do {
	 let ptData = try encoder.encode(thePoint)
	 if let env = paneRec.focus as? CNEnvelopment{
															 env.dagObjPos[each.uuid] = ptData
													 }
} catch {
debugPrint("tring to convert a Point to a Data, in updateLayout in CDEditorDel")
}
}
if var env = paneRec.focus as? CNEnvelopment{
env.dagObjs += droppedItems
}
}
return retVal
}
forgive formatting and code issues. it works just fine, but I had a heck of a time fixing the formatting in the Forum editor. There's likely now, a LOT of text that used to be comments... how could that be any worse? Anyway, "if let newPlistData = pasteBoard.propertyList(forType: CNDragTypeToolBox){}" is the line. if that is not called, the drop pasteboard is empty, if it is called, my objects are there.
I don't need that object, it has nothing at all to do with anything I am doing. Why is it necessary?
also: @Apple... you really messed up the forums. this is so difficult to work with.
I have long since gone through converting my classes to support Codable, And I had an issue where I was using one of the powerful features of Objective programming, inheritance, to make an Array of a generic class, and populate it with subclasses of that class.
You can't just decode that array with the generic class type, you have to tear apart the array into separate arrays of the various subclass types, archive them and when you decode them, merge them back into that single array.
I get 'why' Codable forces you to name the type before you decode the object. security. makes sense. I'm 100% on board.
but I need to be able to duplicate the effect of having a Generically typed array, with subclasses in it, that can be saved to disk.
originally, I created an intermediate class that did tear apart the array, and then put it back together. The main issue with this is: it is impossible to make it portable. You'd have to write an entire class per array type. Further, it becomes unworkable when you cannot know the subclass type in advance, which I am working on right now. I'm adding plugin support. So the classes in the main bundle cannot know anything about the classes in the plugins.
I haven't found a way to store dynamic type in a variable, and I suspect that doing that would break the security anyway.
What I'm looking for... is a design pattern that incorporates all the flexibility of the Generically types array, but doesn't run afoul, Codable, while taking into account that I need to be able to add behavior and potentially variable to subclasses hosted in plugins, that will be required to be serialized in the Main bundle.