如何在自定义 UIView 中从 ViewController 传递数据
Posted
技术标签:
【中文标题】如何在自定义 UIView 中从 ViewController 传递数据【英文标题】:How to pass data from ViewController in custom UIView 【发布时间】:2015-04-03 15:48:54 【问题描述】:我的 ViewController 中有一个名为 chordName 的 NSString 变量,它的值是从单独的 TableViewController 中设置的。 我想再次传递此变量,以便在 ViewController 中的自定义视图中使用。
如何从这里传递变量 (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 方法中使用。 我还是新手,所以如果您需要更多代码,请告诉我。
谢谢
//编辑 - 这是自定义视图类:
.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
【问题讨论】:
请同时添加您的自定义视图代码。届时我们可以为您提供更好的帮助。 已将其添加到问题中 我已经添加了一个答案。请检查。 【参考方案1】:以下是您需要在 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
接下来你可以在你的视图控制器中设置viewDidLoad:
方法
self.guitarStringView.chordName = chordName;
【讨论】:
【参考方案2】:如果您的自定义 UIView 显示在您的 UIViewController 中,您应该为您的 UIView 提供一个自定义类,其中包含一个名为 chordName 的属性。您的 UIViewController 应该访问您的 UIView 并将其属性设置为新的 chordName。 你的代码会是这样的
Declare CustomView *myCustomView in your header file
myCustomView = [CustomView new];
[self.view addsubview:myCustomView]
现在需要时,您可以通过以下方式设置值 myCustomView.chordValue = chordValue
【讨论】:
我确实有一个用于该 UIView 的自定义类,但我将如何访问该视图并设置其属性? 你的这个自定义视图,它添加在哪里?是否添加到同一个 UIViewController 中? 是的,它与我希望传递的变量在同一个 ViewController 中以上是关于如何在自定义 UIView 中从 ViewController 传递数据的主要内容,如果未能解决你的问题,请参考以下文章
如何在自定义 Zapier 应用程序中从 Xero 访问特定订单项值?
如何在自定义 UIView 中添加 UITableView?
如何借助 AutoLayout 在自定义 UITableviewCell 中添加自定义 UIView(xib)?
如何让 UITableViewCell 在自定义 UIView 子类上调用 setHighlighted 或 setSelected?