ios - 如何在自定义 UIView 中从 ViewController 传递数据

标签 ios objective-c iphone uiview

我的 ViewController 中有一个名为 chordName 的 NSString 变量,它的值是从单独的 TableViewController 中设置的。 我想再次传递此变量,以便在 ViewController 中的自定义 View 中使用。

我如何从这里传递变量 (viewcontroller.m)

#import "P15ViewController.h"
#import "P15AppDelegate.h"
@interface P15ViewController ()

@end

@implementation P15ViewController

@synthesize intLabel;
@synthesize chordNameLabel;
@synthesize chordName;
- (void)viewDidLoad
{

    self.guitarStringView.delegate = self;
    chordNameLabel.text = chordName; 
    [super viewDidLoad];

}

-(void)guitarStringsView:(GuitarStringsView*)view stringPlucked:(int)index withVelocity:(float)velocity;
{    
    P15AppDelegate* app = [[UIApplication sharedApplication] delegate];
    [app play:index velocity:velocity];
}

@end

进入 UIView 类以在 drawRect 方法中使用。 我对此还是陌生的,所以如果您需要更多代码,请告诉我。

谢谢

//编辑 - 这是自定义 View 类:

.h 

#import <UIKit/UIKit.h>

@class GuitarStringsView;
@protocol GuitarStringsViewDelegate <NSObject>

-(void)guitarStringsView:(GuitarStringsView*)view stringPlucked:(int)index withVelocity:(float)velocity;
@end

@interface GuitarStringsView : UIView

@property (nonatomic) int stringCount;

@property (weak, nonatomic) id <GuitarStringsViewDelegate> delegate;

@end

.m

@interface GuitarStringsView ()
@property (nonatomic, strong) NSMutableArray* touches;
@property (nonatomic, strong) NSMutableArray* timestamps;
@end

@implementation GuitarStringsView

@synthesize stringCount = _stringCount;


- (id)initWithFrame:(CGRect)frame
{
    if ([super initWithFrame:frame])
    {
        [self commonInit];
    }

    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    if ([super initWithCoder:aDecoder])
    {
        [self commonInit];
    }

    return self;
}

- (void)commonInit
{
    // initialise string count and the arrays to log the touches
    self.stringCount = 1;
    self.touches = [[NSMutableArray alloc] initWithCapacity:2];
    self.timestamps = [[NSMutableArray alloc] initWithCapacity:2];
}

// stringCount getter
-(int)stringCount
{
    return _stringCount;
}

// stringCount setter
-(void)setStringCount:(int)stringCount
{
    // clip to >= 1
    if (stringCount < 1)
        stringCount = 1;

    // if changed
    if (stringCount != _stringCount)
    {
        // update
        _stringCount = stringCount;

        // tell the system it needs to redraw this view
        [self setNeedsDisplay];
    }
}

// drawing
- (void)drawRect:(CGRect)rect
{
    // get the "context" which is the place to which we will draw
    CGContextRef currentContext = UIGraphicsGetCurrentContext();

    // save the state (colours, pen width etc) so we can restore it when we're done
    CGContextSaveGState(currentContext);

    // set up fill and stroke colours
    CGContextSetRGBFillColor(currentContext, 0.5, 0.0, 0.0, 1.0);   // dark red
    CGContextSetRGBStrokeColor(currentContext, 0.0, 0.0, 0.0, 1.0); // black

    // set the stroke pen width
    CGContextSetLineWidth(currentContext, 1);

    // fill whole view with fill colour
    CGContextFillRect(currentContext, rect);

    // calculate geometry, divided screen into N sections where N is stringCount + 1
    const int divisions = self.stringCount + 1;
    const CGFloat divisionWidth = self.bounds.size.width / divisions;

    // start at the first string
    CGFloat stringX = divisionWidth;

    for (int i = 0; i < self.stringCount; ++i, stringX += divisionWidth) // move to next string position each time
    {
        // add a line to the path
        CGContextMoveToPoint(currentContext, stringX, 0);
        CGContextAddLineToPoint(currentContext, stringX, self.bounds.size.height);
    }

    // draw the path (the strings)
    CGContextStrokePath(currentContext);

    // restore the context
    CGContextRestoreGState(currentContext);

    //Draw frets
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 2.0);
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
    CGFloat components[] = {0.0, 0.0, 1.0, 1.0};
    CGColorRef color = CGColorCreate(colorspace, components);
    CGContextSetStrokeColorWithColor(context, color);
    for (int i = 1; i < 5; ++i) // move to next fret position each time
    {
        // add a line to the path
        CGContextMoveToPoint(context, 1, (i * 100));
        CGContextAddLineToPoint(context, 300, (i * 100));
    }

    CGContextStrokePath(context);
    CGColorSpaceRelease(colorspace);
    CGColorRelease(color);


    //draw finger markers
    CGColorRef red = [[UIColor redColor] CGColor];
    CGContextRef fingerContext = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(fingerContext, red);
    CGContextFillEllipseInRect(context, CGRectMake(60, 140, 40, 40));

}



- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
{
    // iterate over the touches
    for (UITouch* touch in touches)
    {
        // find just the touches that have just begun (finger down)
        if (touch.phase == UITouchPhaseBegan)
        {
            // add the touch to the touches array
            [self.touches addObject:touch];

            // get the timestamp of the touch and add that as an NSNumber to the timestamps array
            NSNumber* timestamp = [NSNumber numberWithDouble:touch.timestamp];
            [self.timestamps addObject:timestamp];
        }
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // calculate geometry, divided screen into N sections where N is stringCount + 1
    const int divisions = self.stringCount + 1;
    const CGFloat divisionWidth = self.bounds.size.width / divisions;

    // iterate over the touches
    for (UITouch* touch in touches)
    {
        // find just the touches that have just moved 
        if (touch.phase == UITouchPhaseMoved)
        {
            // compare the timestamps of the last time we saw this touch and now
            // to get the duration since we last saw this touch
            const int timestampIndex = [self.touches indexOfObject:touch];
            NSNumber* prevTimestampObject = self.timestamps[timestampIndex];

            const NSTimeInterval prevTimestamp = [prevTimestampObject doubleValue];
            const NSTimeInterval thisTimestamp = touch.timestamp;
            const NSTimeInterval duration = thisTimestamp - prevTimestamp;

            // get the previous and current x positions of this touch
            const CGFloat hereX = [touch locationInView:self].x;
            const CGFloat prevX = [touch previousLocationInView:self].x;

            CGFloat stringX = divisionWidth;

            // iterate over the strings
            for (int i = 0; i < self.stringCount; ++i, stringX += divisionWidth)
            {
                // did the touch cross this string since the last time we saw this touch?
                if (((prevX < stringX) && (hereX >= stringX)) ||
                    ((prevX > stringX) && (hereX <= stringX)))
                {
                    // calculate a velocity value based on the speed the finger was moving
                    const CGFloat distance = fabsf (hereX - prevX) / self.bounds.size.width;
                    const CGFloat velocity = (distance / duration) / self.stringCount;

                    // send the pluck message to our delegate, clipping velocity to <= 1
                    [self.delegate guitarStringsView:self
                                       stringPlucked:i
                                        withVelocity:velocity < 1 ? velocity : 1.f];
                }
            }

            // update the strored timestamp for this touch for next time
            self.timestamps[timestampIndex] = [NSNumber numberWithDouble:thisTimestamp];
        }
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    // iterate over the touches
    for (UITouch* touch in touches)
    {
        // just get touches that have ended or have been cancelled
        if ((touch.phase == UITouchPhaseEnded) ||
            (touch.phase == UITouchPhaseCancelled))
        {
            // get the index of this touch in our touches array
            const int index = [self.touches indexOfObject:touch];

            // remove the touch from the touches array
            [self.touches removeObjectAtIndex:index];

            // remove the associated timestamp
            [self.timestamps removeObjectAtIndex:index];
        }
    }
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    // do same as touchesEnded: in this case
    [self touchesEnded:touches withEvent:event];
}


@end

最佳答案

以下是您需要在 GuitarStringsView

中进行的更改
#import <UIKit/UIKit.h>
@class GuitarStringsView;
@protocol GuitarStringsViewDelegate <NSObject>
-(void)guitarStringsView:(GuitarStringsView*)view stringPlucked:(int)index withVelocity:(float)velocity;
@end

@interface GuitarStringsView : UIView
@property (nonatomic) int stringCount;
@property(nonatomic) NSString *chordName;
@property (weak, nonatomic) id <GuitarStringsViewDelegate> delegate;
@end

接下来你可以在你的 View Controller 中设置viewDidLoad:方法

self.guitarStringView.chordName = chordName;

关于ios - 如何在自定义 UIView 中从 ViewController 传递数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29435428/

相关文章:

ios - Swift 推断闭包参数之谜

ios - 关于CloudKits的几个问题

iphone - 弃用的 TransactionReceipt

iphone - 如何只重复图像的一部分?

iPhone SDK : Storing username and password in the code

iphone - 在 GPUImage 中实现一个简单的自适应阈值

ios - 如何在 ios 中根据图像动态更改 UI 按钮的宽度和高度

ios - 如何在uiwebview中调用https url?

objective-c - 在 Objective-C 中使用文件偏移量

iphone - 如何使用键值编码判断对象是否存在键?