Mac 使用Objective-C和AppleScript脚本交互

新建Xcode工程,选择macOS平台,选择Other类型中的AppleScript App。
在工程中找到appleScript后缀文件,在applicationWillFinishLaunching_方法中添加测试代码,此处以Safari为例。

on applicationWillFinishLaunching_(aNotification)
	-- Insert code here to initialize your application before any files are opened
    	--Safari打开网页
        tell application "Safari"
            activate
            --新建tab页,传入URL
            tell front window
                --get every tab
                --get URL of tab 1
                make new tab with properties {
     URL:"https://www.apple.com.cn"}
            end tell
        end tell
end applicationWillFinishLaunching_

编译运行后回在控制台报错:*** -[AppDelegate applicationWillFinishLaunching:]: Not authorized to send Apple events to Safari. (error -1743)
是因为App还没有获取到发送AppleScript事件的用户权限,所以不能直接控制Safari打开网页,在Xcode工程中的info.plist中添加Privacy - AppleEvents Sending Usage Description,后面添加上描述,再次启动就会弹出授权弹框。
Mac 使用Objective-C和AppleScript脚本交互_第1张图片
Mac 使用Objective-C和AppleScript脚本交互_第2张图片

最终AppDelegate.applescript文件完整示例代码

script AppDelegate
	property parent : class "NSObject"
	
    -- 载入OC类
    property Test : class "Test"
    
	-- IBOutlets
	property theWindow : missing value
	
	on applicationWillFinishLaunching_(aNotification)
		-- Insert code here to initialize your application before any files are opened
        
        --Safari打开网页
        tell application "Safari"
            activate
            --新建tab页,传入URL
            tell front window
                --get every tab
                --get URL of tab 1
                make new tab with properties {
     URL:"https://www.apple.com.cn"}
            end tell
        end tell
       
        -- 测试OC和AppleScript方法互相调用
        Test's testListParaMethod() --测试OC给脚本方法传数组参数
        Test's testDictParaMethod() --测试OC给脚本方法传字典参数
        Test's testNOParaMethod() --测试OC给脚本不传参数
        set theParaStr to get Test's testRetrunParaMethod() as text --测试通过OC方法获取返回值
        log theParaStr & " "  & (class of theParaStr) --打印返回值及类型
        
	end applicationWillFinishLaunching_
	
	on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits 
		return current application's NSTerminateNow
	end applicationShouldTerminate_
	
end script

其中Test.h

// 测试OC和script互相调用

#import 

NS_ASSUME_NONNULL_BEGIN

@interface Test : NSObject

/** 测试数组传参方法 */
+ (void)testListParaMethod;

/** 测试字典传参方法 */
+ (void)testDictParaMethod;

/** 测试无参数方法 */
+ (void)testNOParaMethod;

/** 测试OC返回值 */
+ (NSString *)testRetrunParaMethod;

@end

NS_ASSUME_NONNULL_END

Test.m

#import "Test.h"

@implementation Test

/** 测试数组传参方法 */
+ (void)testListParaMethod
{
     
    // 获取script类
    // id TestScript = objc_lookUpClass("TestScript");
    id TestScript = NSClassFromString(@"TestScript");
    // 通过SEL来调用script类方法
    SEL listParasSel = NSSelectorFromString(@"testMethodWithListParas:");
    if ([TestScript respondsToSelector:listParasSel]) {
     
        [TestScript performSelector:listParasSel withObject:@[@"first", @"second", @"third"]];
    }
}

/** 测试字典传参方法 */
+ (void)testDictParaMethod
{
     
    // 获取script类
    // id TestScript = objc_lookUpClass("TestScript");
    id TestScript = NSClassFromString(@"TestScript");
    // 通过SEL来调用script类方法
    SEL dictParasSel = NSSelectorFromString(@"testMethodWithDictParas:");
    if ([TestScript respondsToSelector:dictParasSel]) {
     
        [TestScript performSelector:dictParasSel withObject:@{
     @"theName" : @"mike", @"theAge" : @"18"}];
    }
}

/** 测试无参数方法 */
+ (void)testNOParaMethod
{
     
    // 获取script类
    // id TestScript = objc_lookUpClass("TestScript");
    id TestScript = NSClassFromString(@"TestScript");
    // 通过SEL来调用script类方法
    SEL noParasSel = NSSelectorFromString(@"testMethodWithNoParas");
    if ([TestScript respondsToSelector:noParasSel]) {
     
        [TestScript performSelector:noParasSel];
    }
}

/** 测试OC返回值 */
+ (NSString *)testRetrunParaMethod
{
     
    return @"15";
}

@end

TestScript.applescript

script TestScript
	property parent : class "NSObject"
    
    -- 测试数组方式传参
    on testMethodWithListParas_(parasList)
        log "parasList = "
        log parasList
        -- 数组传参形式获取参数
        set parasListList to parasList as list --将OC中的__NSArrayI转为AppleScript中的 <NSAppleEventDescriptor: 'list'> (即list)
        set str1 to item 1 of parasListList
        set str2 to item 2 of parasListList
        log "str1 = " & str1 & ", " & "str2 = " & str2
        log "parasList's class = "
        log class of parasList
    end testMethodWithListParas_
    
    -- 测试字典方式传参
    on testMethodWithDictParas_(parasDict)
        log "parasDict = "
        log parasDict
        -- 字典传参形式获取参数
        set parasRecord to parasDict as record --将OC中的__NSDictionaryI转为 <NSAppleEventDescriptor: 'reco'> (即record)
        set nameStr to theName of parasRecord
        set ageStr to theAge of parasRecord
        log "nameStr = " &  nameStr & ", " & "ageStr = " & ageStr
        log "parasDict's class = "
        log class of parasDict
    end testMethodWithDictParas_
    
    -- 测试无传参
    on testMethodWithNoParas()
        log "No Paras"
    end testMethodWithNoParas
    
end script

如果不想从头创建工程,可以直接看这个Demo —> Objective-C和AppleScript语言交互

你可能感兴趣的:(AppleScript,Mac)