使用SBSettings切换打开或关闭事物 [英] Using SBSettings Toggles to Turn Things On or Off

查看:112
本文介绍了使用SBSettings切换打开或关闭事物的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试使用SBSettings切换打开或关闭的东西 - 如飞机模式,WiFi,SSH等 - 但我无法弄清楚为什么我的代码适用于其中一些切换而不是所有。当然,我只谈论简单的切换;不要用自己的控件(如音量或亮度)调出自己的窗口。我已经能够成功打开/关闭3G,数据,我的铃声,mywi切换......这样的事情,但我无法理解为什么一些切换 - 飞机模式,蓝牙,WiFi - 上我的手机不会响应与上述其他内容相同的代码。

I've been trying to use SBSettings toggles to turn things on or off--like Airplane Mode, WiFi, SSH, etc--but I just can't figure out why my code works for some of these toggles and not all. Granted, I'm only talking about "simple" toggles; not toggles that bring up their own window with their own controls like for volume or brightness. I've been able to successfully turn on/off 3G, data, my ringer, the mywi toggle... things like that, but I can't figure why some of the toggles--Airplane Mode, Bluetooth, WiFi--on my phone won't respond to the same code that works with the other things mentioned above.

以下是我正在使用的一些代码:

Here's some of the code I'm using:

//.h
#import <UIKit/UIKit.h>
#import <sys/stat.h>
#include "/usr/include/dlfcn.h"

typedef enum toggleTypes
{
    SIMPLE,
    NOT_SIMPLE
} ToggleTypes;

typedef bool (*BoolFn)();
typedef void (*VoidBoolFn)(bool b);

@interface Toggle : NSObject
@property (strong, nonatomic) NSString *toggleName;
@property (nonatomic) ToggleTypes toggleType;

- (Toggle *) initWithFullPath:(NSString *) togglePath;
- (BOOL) isEnabled;
- (BOOL) isCapable;
- (BOOL) getStateFast;
- (void) setState:(BOOL) state;

@end
//.m
@implementation Toggle {
    @private
    void *_dylibHandle;
    BoolFn _isCapable;
    BoolFn _isEnabled;
    BoolFn _getStateFast;
    VoidBoolFn _setState;
}

@synthesize toggleName = _toggleName;
@synthesize toggleType = _toggleType;

- (Toggle *) initWithFullPath:(NSString *) togglePath
{
    self.toggleName = [[togglePath stringByDeletingLastPathComponent] lastPathComponent];
    const char *fullName = [togglePath UTF8String];
    struct stat fstat;
    if( stat(fullName, &fstat) != 0 )
    {
        NSLog(@"Reading error for file %s", fullName);
        return nil;
    }
    dlerror();

    _dylibHandle = dlopen(fullName, RTLD_LAZY | RTLD_LOCAL );
    if( !_dylibHandle)
    {
        NSLog(@"dlopen encountered an error and did not open file: %s", fullName);
        return nil;
    }

    dlerror();
    _isCapable = dlsym(_dylibHandle, "isCapable");
    char *error = dlerror();
    if( !_isCapable )
    {
        NSLog(@"An error was encountered while loading symbol \"isCapable\"\nFile: %s\nError: %s", fullName, error);
        return nil;
    }

    _isEnabled = dlsym(_dylibHandle, "isEnabled");
    error = dlerror();
    if( !_isCapable )
    {
        NSLog(@"An error was encountered while loading symbol \"isEnabled\"\nFile: %s\nError: %s", fullName, error);
        return nil;
    }

    _getStateFast = dlsym(_dylibHandle, "getStateFast");
    error = dlerror();
    if( !_isCapable )
    {
        NSLog(@"An error was encountered while loading symbol \"getStateFast\"\nFile: %s\nError: %s", fullName, error);
        return nil;
    }

    _setState = dlsym(_dylibHandle, "setState");
    error = dlerror();
    if( !_isCapable )
    {
        NSLog(@"An error was encountered while loading symbol \"getStateFast\"\nFile: %s\nError: %s", fullName, error);
        return nil;
    }

    NSArray *windowsBefore = [[[[UIApplication sharedApplication] windows] objectAtIndex:0] subviews];
    [self setState:[self isEnabled]];
    NSArray *windowsAfter = [[[[UIApplication sharedApplication] windows] objectAtIndex:0] subviews];

    if( [windowsAfter count] > [windowsBefore count] ) {
        self.toggleType = NOT_SIMPLE;
        for (UIView *view in windowsAfter) {
            if( ![windowsBefore containsObject:view] )
                [view removeFromSuperview];
        }
    } else { 
        self.toggleType = SIMPLE;
    }

    return self;
}

- (BOOL) isEnabled
{
    return _isEnabled();
}

- (BOOL) isCapable
{
    return _isCapable();
}

- (BOOL) getStateFast
{
    return _getStateFast();
}

- (void) setState:(BOOL) state
{
    _setState(state);
}

- (void) dealloc
{
    dlclose(_dylibHandle);
}
@end

调用的代码initWithFullPath

if( [directoryToggleNames objectForKey:toggleName] == nil ) {
    if ((strlen(SBTOGGLES_PATH) + strlen([toggleName UTF8String] + strlen("/Toggle.dylib")) + 1) > _POSIX_PATH_MAX) {
        NSLog(@"Toggle %@ has a path name that is too long", toggleName);
        return nil;
    }
    char fullName[_POSIX_PATH_MAX + 1];
    strcpy(fullName, SBTOGGLES_PATH);
    strcat(fullName, [toggleName UTF8String]);
    strcat(fullName, "/Toggle.dylib");

    NSString *fullPath = [NSString stringWithUTF8String:fullName];
    return [[OSToggle alloc] initWithFullPath:fullPath];
}

return [[OSToggle alloc] initWithFullPath:[directoryToggleNames objectForKey:toggleName]];

使用上述代码的代码和切换类本身:

The code that uses the code above and the toggle class itself:

ToggleScanner *scanner = [ToggleScanner getInstance];
NSDictionary *toggleDict = [self getToggleDictionary];
for (ToggleBase *t in [toggleDict allValues] ) {
    OSToggle *toggle = [scanner getToggleByName:t.name];
    if( [t.type isEqualToString:@"simple"] ) {
        NSLog(@"isCapable: %@; isEnabled: %@", ( [toggle isCapable] ? @"YES" : @"NO" ),  ( [toggle isEnabled] ? @"YES" : @"NO" ));

        [toggle setState:t.state.boolValue];
        NSLog(@"Set toggle, %@, to %@; result isEnabled: %@", t.name, ( t.state.boolValue ? @"YES" : @"NO" ), ( [toggle isEnabled] ? @"YES" : @"NO" ) );
    } else {
        NSLog(@"Toggle is not a simple type");
    }
}

ToggleScanner只查看SBSettings切换目录并构建一个基于它在那里找到的切换的字典。 getToggleDict是一种方法,它将NSData对象从CoreData中取出并将其转换为一组切换,并指出我可以依次执行。 ToggleBase只是一个信息保持类;它没有方法。

ToggleScanner just looks in the SBSettings toggle directory and builds a dictionary based on the toggles it finds there. getToggleDict is a method that takes a NSData object out of CoreData and turns it into a set of toggles and state that I can, in turn, execute. ToggleBase is just an information holding class; it has no methods.

它的粗糙,但它适用于一些切换。问题是:我在这里做错了吗?飞行模式和3G切换都是简单的开/关切换,但此代码适用于3G切换,但不适用于飞行模式。任何想法,评论和/或建议为什么会这样?

Its rough, but it works on some of the toggles. The question is: Is there something I'm doing wrong here? Both the Airplane Mode and the 3G toggle are simple on/off switches, yet this code works on the 3G toggle but not the Airplane Mode one. Any ideas, comments, and/or suggestions as to why this is?

编辑1:添加了调用切换类的代码及其中的一些描述。

Edit 1: Added code that calls the toggle class and some descriptions about it.

推荐答案

我的想法与您最初的想法相似,我尝试过连接到SBSetting的每个toggle.dylib以打开/关闭3G,Wi-Fi,MyFi。但是,我只能让它适用于3G切换。我无法弄清楚如何使其适用于MyFi切换。您使用的是什么版本的MyFi?

My idea is similar to your original idea, I try to hook up to each toggle.dylib of SBSetting to turn on/off 3G, Wi-Fi, MyFi. However, I could only make it work for 3G toggle. I could not figure out how to make it work for MyFi toggle too. what version of MyFi did you use?

这篇关于使用SBSettings切换打开或关闭事物的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆