Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use NSRange as a Block parameter? #32

Open
elliotnash opened this issue Nov 15, 2021 · 1 comment
Open

How to use NSRange as a Block parameter? #32

elliotnash opened this issue Nov 15, 2021 · 1 comment

Comments

@elliotnash
Copy link

elliotnash commented Nov 15, 2021

I'm looking to create a block that takes an NSRange, and it seems I can't use a struct as a parameter, as I get TypeError: Unable to coerce type from [StructType] when supplying objc.types.NSRange as a type. Any ideas on how to do this? I'm also not sure how to create a block that takes primitives or the BOOL type (I'm trying to create a block of type ^(NSDictionary *attrs, NSRange range, BOOL *stop) {}

@lukaskollmer
Copy link
Owner

lukaskollmer commented Nov 17, 2021

Fixed this, it should now work with the v0.22.0 release. Here's an example of using a block with the signature you mentioned (I also added this to the examples/ folder).

const objc = require('objc');
const ref = require('ref-napi');

objc.import('AppKit'); // for NSLinkAttributeName

const { id, NSRange } = objc.types;
const {
    NSAttributedString,
    NSMutableAttributedString,
    NSLinkAttributeName
} = objc;


let attrString = NSMutableAttributedString.new();
attrString.appendAttributedString_(NSAttributedString.alloc().initWithString_attributes_(
    'abc', { [NSLinkAttributeName]: 'https://example.com' }
));
attrString.appendAttributedString_(NSAttributedString.alloc().initWithString_attributes_(
    'def', { [NSLinkAttributeName]: 'https://example.de' }
));


let block = new objc.Block((arg0, arg1, arg2) => {
    const attrs = objc.wrap(arg0);
    const range = arg1;
    console.log(`block called w/ args attrs: ${attrs}, range: ${[arg1.location, arg1.length]}, stop: ${arg2.deref()}`);
    //ref.set(arg2, 0, 1); // uncomment this to have it stop iterating after the first range.
    return;
}, objc.types.void, [id, NSRange, ref.refType(objc.types.char)]);

attrString.enumerateAttributesInRange_options_usingBlock_(NSRange.new(0, attrString.length()), 0, block);

The block args arg0, arg1, and arg2 are the NSDictionary *, NSRange, and BOOL * args, respectively.
You can use the location and length properties to access the fields of the range struct inside the block. The first param (the attributes dict) needs to be wrapped in an objc instance proxy using the objc.wrap function.

This also supports writing to the stop param, you can uncomment the commented line in the block to test that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants