草庐IT

ios - 钛模块开发 : Invalid method createView

coder 2024-01-19 原文

过去几个小时我一直在搜索,但我无法弄清楚。我正在 Obj-C 中为 iOS 创建一个钛模块。该模块编译正常。我的测试项目可以看到该模块,但是,我不断收到此错误:

在 app.js 中传递给 TiVolumesliderModule 的方法 (createView) 无效

我的 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

最佳答案

根据以往的经验,这可能是由一些不同的原因引起的。

文件名的大小写和前缀很重要。我发现 View 和 View 代理有些不一致。确保所有内容都有此前缀:TiVolumeslider(带有小写的 s),后跟 ModuleViewViewProxy。 Titanium 做了一些魔术,将 ViewProxiesModule 相关联,并将 ViewViewProxy 相关联。

接下来,确保 View 和 View 代理 .h 和 .m 文件已添加到 Xcode 项目中。在Xcode中打开TiVolumeslider.xcodeproj,将4个 View / View 代理.h和.m文件拖到Classes组中。它会询问您是否要将它们添加到各种目标,您可以这样做,因此保留默认设置,添加文件,然后重试。

关于ios - 钛模块开发 : Invalid method createView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21392232/

有关ios - 钛模块开发 : Invalid method createView的更多相关文章

  1. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  3. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  4. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  5. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  6. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

  7. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  8. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  9. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  10. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

随机推荐