Folks,
I’m trying (for tests of third party hardware) to set up a very simple ‘UDP parrot’. It receives a packet, and returns it to the source with a '*' prefixed.
Can’t get it work. The following code works like a charm on FreeBSD, but won’t work on MacOS:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/errno.h>
#include <string.h>
int main(int argc, const char * argv[]) {
struct sockaddr_in myAddr;
struct sockaddr_in rmtAddr;
socklen_t rmtAddrLength;
char buffer [2048];
char src [256];
printf ("Opening socket…\n");
int sock;
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
printf("Cannot open UDP socket. Bailing!\n");
return -1;
}
int opt = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
myAddr.sin_family = AF_INET;
myAddr.sin_addr.s_addr = INADDR_ANY;
myAddr.sin_port = htons(5522);
if (bind(sock, (struct sockaddr *) &myAddr, sizeof(myAddr))) {
printf ("Error binding socket -> %d\n", errno);
return -1;
}
printf ("Listening…\n");
while (1) {
ssize_t dataLength = recvfrom(sock, buffer + 1, sizeof(buffer) - 1,
0, (struct sockaddr *)& rmtAddr, & rmtAddrLength);
printf ("Received %zd bytes: %s\n", dataLength, buffer);
printf ("addrLength: %d\n", rmtAddrLength);
inet_ntop(AF_INET, & rmtAddr.sin_addr, src, sizeof(src));
printf("From %s port %d\n", src, ntohs (rmtAddr.sin_port));
if (! strncmp (buffer + 1, "STOP", 4)) {
sendto (sock, "Terminated\n", 11, 0,
(struct sockaddr *)& rmtAddr, sizeof(rmtAddr));
break;}
buffer [0] = '*';
dataLength = sendto(sock, buffer, dataLength + 1, 0,
(struct sockaddr *)& rmtAddr, sizeof(rmtAddr));
}
return 0;
}
The problem is, the rmtAddr structure, which is supposed to contain the IP address of the remote sender, well, does not. I always get 1.0.0.0 instead. As I said before, I have no such problem with the exact same code on FreeBSD. Also, rmtAddrLength, which is 8 on FreeBSD, is 16 on MacOS apparently.
I've dumped the memory starting at &rmtAddr and did not see a hint of a possible IP address.
Any idea what could be wrong?
Thanks !
V.
Post
Replies
Boosts
Views
Activity
Folks,
I have finally gotten to implement a sort of lazy loading OutlineGroup. The idea is to load only the parts of the tree the OutlineGroup displays. Why? Because the underlying item (can be huge, can contain big text or spreadsheets) is externally fetched from a server, and unfortunately I have no way to ask the server to send me a 'summary' version with, say, only name and ID. :(
So the code is this:
OutlineGroup(displayTree, id: \.id, children: \.children) {item in
Text ("\(item.name) - (\(item.id))")
.onAppear {Task {await loadAllChildrenOfItemID(id: item.id)}}
.foregroundColor(item.children == nil ? .white : .blue)}
}
As you can see, the line containing the name of the item changes whether the item is a node or a leaf in the tree of items.
Lazy loading seems to work: the items are not loaded until their ‘parent’ gets displayed in the OutlineGroup after several hierarchical unfolding operations. However, at some point, I always get an inconsistent behaviour: I get blue names (meaning, the item has children), but the folding/unfolding button > does not show up in the list.
I can also mention that loading children of a given item leads to regeneration of displayTree, which is basically a tree of structs containing only the ID and the name of the item.
The attached screenshot is typical of that curious misbehaviour. Both lines are blue, they should be preceded by the > button, but only one has it.
If I fold and unfold the parent item, I get all > as they should appear, so could this be a rat race?
Folks,
I’m writing a private app to browse through HTML contents stored on a website using that website's API. Everything works perfectly, except when I want to add a custom CSS to pretty print the contents.
I’m using a WKWebView suitably piggybacked to a SwiftUI view, and tried and use a small JS script to inject the CSS into the loaded page. The method I found makes use of WKUserContentController and creates a user script which is (purportedly) loaded after the page is rendered.
But that doesn’t work. The JS script is injected alright, but the view does not update. Worse, if I select another HTML chunk from the list of available pages, the chunk loads fine but the CSS is not applied. So the view does update, but spurns the script.
Yet, if I switch to an HTML source view, which kills the WKWebView instance, and then bring it back in, the CSS miraculously activates.
So, am I wrong, or shall I deduce that WKUserContentController's scripts are executed only once, when the view appears? What's more puzzling is that the updateNSView method of the wrapping view (which itself calls loadHTMLString) is correctly called after the CSS has been injected, so that should result in a view update, but it doesn’t.
What gives?
For reference, this is the piggybacking object:
struct WebView: NSViewRepresentable {
typealias NSViewType = WKWebView
let webView: WKWebView
let wkUCC = WKUserContentController()
let wkConfig = WKWebViewConfiguration()
var HTML: String?
var zoom: Double
var CSS: String?
init(HTML: String?, CSS: String?, zoom: Double) {
wkConfig.userContentController = wkUCC
self.webView = WKWebView(frame: CGRect.zero, configuration: wkConfig)
self.HTML = HTML
self.zoom = zoom
self.CSS = CSS
if let css = CSS {
loadCSS(css: css)
}
}
func loadCSS (css: String) {
let script = """
var oldStyles = document.getElementsByTagName('style');
if (oldStyles != null) {
for (let oldStyle of oldStyles) {
document.head.removeChild(oldStyle);
}
}
var newStyle = document.createElement('style');
newStyle.innerHTML = '\(css)';
var result = document.head.appendChild(newStyle);
"""
.replacing(/\n/, with: "")
let userScript = WKUserScript(source: script,
injectionTime: .atDocumentEnd,
forMainFrameOnly: true)
wkUCC.removeAllUserScripts()
wkUCC.addUserScript(userScript)
}
func makeNSView(context: Context) -> WKWebView {
return webView
}
func updateNSView(_ webView: WKWebView, context: Context) {
if var HTML = self.HTML {
webView.loadHTMLString(HTML, baseURL: nil)
webView.pageZoom = zoom
}
}
}
and the calling code in the wrapping view:
if displaySource {
TextEditor(text: Binding<String>(get: {item.HTML}, set:{_ in}))
.font(.system(size: zoom * 14, weight: .light, design: .monospaced))
.padding(.horizontal, 5)
} else {
WebView(HTML: item.HTML, CSS: CSS, zoom: zoom)
.padding(.horizontal, 5)
}
P.S: I tried to use various decorators such as @State and @Biding to shake things up, but to no avail.
Folks,
I have a SwiftUI view with a fairly simple table, nothing fancy:
Table(itemsToDisplay, selection: $selectedLines, sortOrder: $sortOrder)
{…}
Then I have created a Deselect all command added in the Edit menu, which toggles a boolean state variable called deselect, and I've written this modifier:
.onChange(of: deselect) {_ in selectedLines = Set<TableEntry.ID>(); deselect = false}
While this correctly deselects all visible rows, it turns out the hidden rows are not deselected and show up highlighted when the table is scrolled up or down. Is that the expected behaviour? How am I supposed to deselect all rows, including the invisible ones?
Thanks a bunch!
V.
P.S: I’m using the latest MacOS 13 beta SDK with the latest Xcode beta (14.1ß3)
Folks,
I’m trying to navigate through a tree using … well, some SwiftUI widget. I've tried OutlineGroup and it works, but the big drawback is that you can’t lazily download the tree, since there is no state variable of sorts that informs you when a disclosure sign > is pressed. So you have to download the whole tree at once, including items that you’re likely no to view ever.
I tried the new NavigationStack, with that sort of idea:
NavigationStack {
RecursiveView (rootItemList)
}
struct RecursiveView (itemList) {
List {
ForEach (item in itemList) {
if item.isLeaf {
someView (item)
} else {
NavigationLink (destination: RecursiveView(childList))
}
}
}
Well, it does work up to one level of recursion. Afterwards, it stops working and I get these messages:
onChange(of: UpdateTrigger) action tried to update multiple times per frame
or/and:
Only root-level navigation destinations are effective for a navigation stack with a homogeneous path.
So I suppose this widget is not fit for that kind of navigation. Does anyone have a better idea?
Folks,
I’m writing an app which asks its user for credentials, logs into a server, retrieves data using the credentials entered, and then presents the data on screen. Very simple (so far).
I thus have written a SwiftUI app that chains two scenes, corresponding to the two phases of the app:
import SwiftUI
@main
struct MyApp: App {
@StateObject var stateObjectInstance = StateObject ()
var body: some Scene {
Window {
if !stateObjectInstance.hasValidCredentials {
someViewToAskAndCheckForCredentials
}
}
Window {
if stateObjectInstance.hasValidCredentials {
someViewToDisplayData
}
}
}
}
Problem is, I get inconsistent behaviour. This work the first time I execute the code. Then, it doesn’t: either both, or only the second, scene(s) don’t show up. If I swap the Window {} blocks in the code, then it works fine again, but only once.
So my question is: is this expected behaviour because I got something wrong, is this caused by, say, some persistent state being restored whereas it should not, or is this a bug?
Thanks a bunch!
Folks,
I’m try to write a brand new MacOS app from scratch using Swift UI and concurrency… Quite a steep learning curve to learn how to mix the two.
Anyway, I think I’m getting the hang of it now, but I’m faced with a small glitch. I have a simple form to start with in order to input credentials to log into a server where the data to display is (REST API). Valid credentials are pre-filled in the Form Text/SecureField. But as soon as I try to edit (just testing) one of the fields, a spurious outline appears (see attached screenshots). Sometimes that outline appears when the window closes and another one pops up as a segue. If I hide the window under, say, the Xcode main window and raise it back, the spurious outline disappears, so that’s definitely a remnant of a transient operation.
I wonder where is the bug responsible for that. I don’t see what could cause such a ‘ghost’ to show up, but I might be just overlooking it. Has anyone experienced the same thing?
To solve a dependency tangle on an app, I’m trying to write a simple command line tool that would display all the dependencies of a given app or library, and output it in a format suitable for post-processing by graphviz. The idea here is to collect and lay out the output of the otool -L utility, recursively called on all the dependencies of the target app/lib.
Unfortunately, when I try otool -L with, say, otool itself, I get this:
Dev > otool -L /usr/bin/otool
/usr/bin/otool:
/usr/lib/libxcselect.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.0.0)
Fine. But now:
otool -L /usr/lib/libxcselect.dylib
/Library/Developer/CommandLineTools/usr/bin/objdump: error: '/usr/lib/libxcselect.dylib': No such file or directory
Oops. Indeed, /usr/lib seems mostly empty, and most of what lies inside are links on missing (I assume: invisible) libs.
So my question is: where are all the libs gone, and it is possible to bring them back to the surface?