Titanium模块开发:createView方法无效

时间:2014-01-27 21:39:04

标签: ios objective-c titanium titanium-modules

过去几个小时我一直在寻找,我无法弄清楚这一点。我正在Obj-C中为iOS创建一个钛模块。该模块编译得很好。我的测试项目可以看到模块,但是,我一直收到这个错误:

Invalid method (createView) passed to TiVolumesliderModule at app.js

我的app.js包含

var VolumeSlider = require('ti.volumeslider'); //-- this works
Titanium.API.info("module is => "+VolumeSlider); //-- this works: module is => [object TiVolumesliderModule]

var volumeSlider = VolumeSlider.createView({
  width: '90%',
  height: 'auto',
  color: '#000',
  bottom: 10,
});

我的Obj-C文件如下。我对Obj-C不太熟悉所以我为发布这些长文件而道歉。

TiVolumesliderViewProxy.h

#import "TiViewProxy.h"

@interface TiVolumesliderViewProxy : TiViewProxy {

}

@end

TiVolumesliderViewProxy.m

#import "TiVolumesliderViewProxy.h"
#import "TiVolumesliderView.h"

NSArray* sliderKeySequence;

@implementation TiVolumesliderViewProxy

-(NSArray *)keySequence
{
    if (sliderKeySequence == nil)
    {
        sliderKeySequence = [[NSArray arrayWithObjects:@"value",nil] retain];
    }
    return sliderKeySequence;
}

-(UIViewAutoresizing)verifyAutoresizing:(UIViewAutoresizing)suggestedResizing
{
    return suggestedResizing & ~UIViewAutoresizingFlexibleHeight;
}

USE_VIEW_FOR_VERIFY_HEIGHT

@end

TiVolumesliderView.h

#import "TiUIView.h"
#import <MediaPlayer/MediaPlayer.h>

@interface TiVolumesliderView : TiUIView<LayoutAutosizing> {
@private
    MPVolumeView *sliderView;
    UISlider *volumeViewSlider;
    NSDate* lastTouchUp;
    NSTimeInterval lastTimeInterval;
}

- (IBAction)sliderChanged:(id)sender;

@end

TiVolumesliderView.m

#import "TiVolumesliderView.h"
#import "TiVolumesliderViewProxy.h"
#import "TiApp.h"
#import "TiUtils.h"

@implementation TiVolumesliderView

-(void)dealloc
{
    [volumeViewSlider removeTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
    RELEASE_TO_NIL(sliderView);
    RELEASE_TO_NIL(lastTouchUp);
    [super dealloc];
}

-(MPVolumeView*)sliderView
{
    if (sliderView==nil)
    {
        sliderView = [[MPVolumeView alloc] initWithFrame:[self bounds]];
        [sliderView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
        [self addSubview:sliderView];

        for (UIView *view in [sliderView subviews]) {
            if ([[[view class] description] isEqualToString:@"MPVolumeSlider"]) {
                volumeViewSlider = (UISlider *) view;
            }
        }

        [volumeViewSlider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
        lastTouchUp = [[NSDate alloc] init];
        lastTimeInterval = 1.0; // Short-circuit so that we don't ignore the first fire
    }
    return sliderView;
}

-(BOOL)hasTouchableListener
{
    // since this guy only works with touch events, we always want them
    // just always return YES no matter what listeners we have registered
    return YES;
}

-(void)setThumb:(id)value forState:(UIControlState)state
{
    [volumeViewSlider setThumbImage:[TiUtils image:value proxy:[self proxy]] forState:state];
}

-(void)setRightTrack:(id)value forState:(UIControlState)state
{
    [volumeViewSlider setMaximumTrackImage:[TiUtils stretchableImage:value proxy:[self proxy]] forState:state];
}

-(void)setLeftTrack:(id)value forState:(UIControlState)state
{
    [volumeViewSlider setMinimumTrackImage:[TiUtils stretchableImage:value proxy:[self proxy]] forState:state];
}

#pragma mark View controller stuff

-(void)setThumbImage_:(id)value
{
    [self setThumb:value forState:UIControlStateNormal];
}

-(void)setSelectedThumbImage_:(id)value
{
    [self setThumb:value forState:UIControlStateSelected];
}

-(void)setHighlightedThumbImage_:(id)value
{
    [self setThumb:value forState:UIControlStateHighlighted];
}

-(void)setDisabledThumbImage_:(id)value
{
    [self setThumb:value forState:UIControlStateDisabled];
}

-(void)setLeftTrackImage_:(id)value
{
    [self setLeftTrack:value forState:UIControlStateNormal];
}

-(void)setSelectedLeftTrackImage_:(id)value
{
    [self setLeftTrack:value forState:UIControlStateSelected];
}

-(void)setHighlightedLeftTrackImage_:(id)value
{
    [self setLeftTrack:value forState:UIControlStateHighlighted];
}

-(void)setDisabledLeftTrackImage_:(id)value
{
    [self setLeftTrack:value forState:UIControlStateDisabled];
}

-(void)setRightTrackImage_:(id)value
{
    [self setRightTrack:value forState:UIControlStateNormal];
}

-(void)setSelectedRightTrackImage_:(id)value
{
    [self setRightTrack:value forState:UIControlStateSelected];
}

-(void)setHighlightedRightTrackImage_:(id)value
{
    [self setRightTrack:value forState:UIControlStateHighlighted];
}

-(void)setDisabledRightTrackImage_:(id)value
{
    [self setRightTrack:value forState:UIControlStateDisabled];
}

-(void)setValue_:(id)value withObject:(id)properties
{   
    CGFloat newValue = [TiUtils floatValue:value];

    if (newValue > 1) 
    {
        newValue = 1;
    }
    else if (newValue < 0)
    {
        newValue = 0;
    }

    BOOL animated = [TiUtils boolValue:@"animated" properties:properties def:NO];
    UISlider * ourSlider = volumeViewSlider;
    [ourSlider setValue:newValue animated:animated];
    [[MPMusicPlayerController applicationMusicPlayer] setVolume:newValue];
    [self sliderChanged:ourSlider];
}

-(void)setValue_:(id)value
{
    [self setValue_:value withObject:nil];
}

-(void)setEnabled_:(id)value
{
    [volumeViewSlider setEnabled:[TiUtils boolValue:value]];
}

-(CGFloat)verifyHeight:(CGFloat)suggestedHeight
{
    CGSize fitSize = [[self sliderView] sizeThatFits:CGSizeZero];
    return fitSize.height;
}

USE_PROXY_FOR_VERIFY_AUTORESIZING

#pragma mark Delegates 

- (IBAction)sliderChanged:(id)sender
{
    NSNumber * newValue = [NSNumber numberWithFloat:[(UISlider *)sender value]];
    [self.proxy replaceValue:newValue forKey:@"value" notification:NO];

    if ([self.proxy _hasListeners:@"change"])
    {
        [self.proxy fireEvent:@"change" withObject:[NSDictionary dictionaryWithObject:newValue forKey:@"value"]];
    }
}

@end

TiVolumesliderModule.h

#import "TiModule.h"
#import <MediaPlayer/MediaPlayer.h>

@interface TiVolumesliderModule : TiModule 
{
}

@end

TiVolumesliderModule.m

#import "TiVolumesliderModule.h"
#import "TiApp.h"
#import "TiBase.h"
#import "TiHost.h"
#import "TiUtils.h"

@implementation TiVolumesliderModule

#pragma mark Internal

// this is generated for your module, please do not change it
-(id)moduleGUID
{
    return @"56141681-6e15-4783-a284-e4aa93444757";
}

// this is generated for your module, please do not change it
-(NSString*)moduleId
{
    return @"ti.volumeslider";
}

#pragma mark Lifecycle

-(void)startup
{
    // this method is called when the module is first loaded
    // you *must* call the superclass
    [super startup];

    NSLog(@"[INFO] %@ loaded",self);
}

-(void)shutdown:(id)sender
{
    // this method is called when the module is being unloaded
    // typically this is during shutdown. make sure you don't do too
    // much processing here or the app will be quit forceably

    // you *must* call the superclass
    [super shutdown:sender];
}

#pragma mark Cleanup 

-(void)dealloc
{
    // release any resources that have been retained by the module
    [super dealloc];
}

#pragma mark Internal Memory Management

-(void)didReceiveMemoryWarning:(NSNotification*)notification
{
    // optionally release any resources that can be dynamically
    // reloaded once memory is available - such as caches
    [super didReceiveMemoryWarning:notification];
}

#pragma mark Listener Notifications

-(void)_listenerAdded:(NSString *)type count:(int)count
{
    if (count == 1 && [type isEqualToString:@"my_event"])
    {
        // the first (of potentially many) listener is being added 
        // for event named 'my_event'
    }
}

-(void)_listenerRemoved:(NSString *)type count:(int)count
{
    if (count == 0 && [type isEqualToString:@"my_event"])
    {
        // the last listener called for event named 'my_event' has
        // been removed, we can optionally clean up any resources
        // since no body is listening at this point for that event
    }
}

#pragma Public APIs

-(id)example:(id)args
{
    // example method
    return @"hello world";
}

-(id)exampleProp
{
    // example property getter
    return @"hello world";
}

-(void)exampleProp:(id)value
{
    // example property setter
}


-(id)moduleVersion
{
    // example property getter
    return @"0.1";
}

@end

1 个答案:

答案 0 :(得分:2)

根据过去的经验,这可能是由一些不同的事情造成的。

您的文件名的大小写和前缀很重要。我看到与视图和视图代理有些不一致。确保所有内容都有此前缀:TiVolumeslider(小写s),然后是ModuleViewViewProxy。 Titanium可以将ViewProxiesModule以及ViewViewProxy相关联。

接下来,确保已将视图和视图代理.h和.m文件添加到Xcode项目中。在Xcode中打开TiVolumeslider.xcodeproj,然后将4个视图/视图代理.h和.m文件拖到Classes组中。它会询问您是否要将它们添加到您执行的各种目标中,因此请保留默认值,添加文件,然后重试。