diff --git a/SQNumber/SQNumber.xcodeproj/project.pbxproj b/SQNumber/SQNumber.xcodeproj/project.pbxproj index 33333f77..eb0667b3 100644 --- a/SQNumber/SQNumber.xcodeproj/project.pbxproj +++ b/SQNumber/SQNumber.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 1461A83A250BC1BC006CE5FE /* SQSceneView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1461A839250BC1BC006CE5FE /* SQSceneView.m */; }; 14EABDA3250B57520091F19B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 14EABDA2250B57520091F19B /* AppDelegate.m */; }; 14EABDA6250B57520091F19B /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 14EABDA5250B57520091F19B /* SceneDelegate.m */; }; 14EABDA9250B57520091F19B /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 14EABDA8250B57520091F19B /* ViewController.m */; }; @@ -15,10 +16,11 @@ 14EABDB1250B57530091F19B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 14EABDAF250B57530091F19B /* LaunchScreen.storyboard */; }; 14EABDB4250B57530091F19B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 14EABDB3250B57530091F19B /* main.m */; }; 14EABDC1250B60A10091F19B /* SQSpriteView.m in Sources */ = {isa = PBXBuildFile; fileRef = 14EABDC0250B60A10091F19B /* SQSpriteView.m */; }; - 14EABE11250BB6FA0091F19B /* SQTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = 14EABE0F250BB6F90091F19B /* SQTimer.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 1461A838250BC1BC006CE5FE /* SQSceneView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SQSceneView.h; sourceTree = ""; }; + 1461A839250BC1BC006CE5FE /* SQSceneView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SQSceneView.m; sourceTree = ""; }; 14EABD9E250B57520091F19B /* SQNumber.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SQNumber.app; sourceTree = BUILT_PRODUCTS_DIR; }; 14EABDA1250B57520091F19B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 14EABDA2250B57520091F19B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -33,8 +35,6 @@ 14EABDB3250B57530091F19B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 14EABDBF250B60A10091F19B /* SQSpriteView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQSpriteView.h; sourceTree = ""; }; 14EABDC0250B60A10091F19B /* SQSpriteView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SQSpriteView.m; sourceTree = ""; }; - 14EABE0F250BB6F90091F19B /* SQTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SQTimer.m; sourceTree = ""; }; - 14EABE10250BB6FA0091F19B /* SQTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQTimer.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -73,10 +73,10 @@ 14EABDA5250B57520091F19B /* SceneDelegate.m */, 14EABDA7250B57520091F19B /* ViewController.h */, 14EABDA8250B57520091F19B /* ViewController.m */, + 1461A838250BC1BC006CE5FE /* SQSceneView.h */, + 1461A839250BC1BC006CE5FE /* SQSceneView.m */, 14EABDBF250B60A10091F19B /* SQSpriteView.h */, 14EABDC0250B60A10091F19B /* SQSpriteView.m */, - 14EABE10250BB6FA0091F19B /* SQTimer.h */, - 14EABE0F250BB6F90091F19B /* SQTimer.m */, 14EABDAA250B57520091F19B /* Main.storyboard */, 14EABDAD250B57530091F19B /* Assets.xcassets */, 14EABDAF250B57530091F19B /* LaunchScreen.storyboard */, @@ -158,8 +158,8 @@ files = ( 14EABDA9250B57520091F19B /* ViewController.m in Sources */, 14EABDA3250B57520091F19B /* AppDelegate.m in Sources */, + 1461A83A250BC1BC006CE5FE /* SQSceneView.m in Sources */, 14EABDB4250B57530091F19B /* main.m in Sources */, - 14EABE11250BB6FA0091F19B /* SQTimer.m in Sources */, 14EABDA6250B57520091F19B /* SceneDelegate.m in Sources */, 14EABDC1250B60A10091F19B /* SQSpriteView.m in Sources */, ); diff --git a/SQNumber/SQNumber/SQScene.h b/SQNumber/SQNumber/SQScene.h new file mode 100644 index 00000000..de7c136c --- /dev/null +++ b/SQNumber/SQNumber/SQScene.h @@ -0,0 +1,19 @@ +// +// SQScene.h +// SQNumber +// +// Created by 朱双泉 on 2020/9/11. +// Copyright © 2020 朱双泉. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface SQSceneView : NSObject + +- (instancetype)initWithCapacity:(NSUInteger)capacity; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SQNumber/SQNumber/SQScene.m b/SQNumber/SQNumber/SQScene.m new file mode 100644 index 00000000..9a447743 --- /dev/null +++ b/SQNumber/SQNumber/SQScene.m @@ -0,0 +1,85 @@ +// +// SQScene.m +// SQNumber +// +// Created by 朱双泉 on 2020/9/11. +// Copyright © 2020 朱双泉. All rights reserved. +// + +#import "SQSceneView.h" +#import + +@implementation SQSceneView + +- (instancetype)initWithCapacity:(NSUInteger)capacity { + self = [super init]; + if (self) { + NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:capacity]; + + UIView *containerView = [UIView new]; + CGFloat containerViewW = self.view.bounds.size.width * 0.9; + CGFloat containerViewH = containerViewW * 0.2; + CGFloat containerViewX = (self.view.bounds.size.width - containerViewW) * 0.5; + CGFloat containerViewY = (self.view.bounds.size.height - containerViewH) * 0.5; + containerView.frame = CGRectMake(containerViewX, containerViewY, containerViewW, containerViewH); + [self.view addSubview:containerView]; + + CGFloat innerViewW = containerViewH - 20; + CGFloat innerViewH = innerViewW; + CGFloat innerViewY = (containerViewH - innerViewH) * 0.5; + CGFloat innerViewS = (containerViewW - (innerViewW * capacity)) / (capacity + 1); + CGFloat movableViewW = innerViewW - 20; + CGFloat movableViewH = movableViewW; + for (NSInteger i = 0; i < capacity; i++) { + UIView *innerView = [UIView new]; + CGFloat innerViewX = innerViewS + (i * (innerViewW + innerViewS)); + innerView.backgroundColor = [UIColor lightGrayColor]; + innerView.frame = CGRectMake(innerViewX, innerViewY, innerViewW, innerViewH); + [containerView addSubview:innerView]; + + UILabel *innerLabel = [UILabel new]; + innerLabel.text = @(i + 1).stringValue; + innerLabel.textAlignment = NSTextAlignmentCenter; + innerLabel.font = [UIFont boldSystemFontOfSize:120]; + innerLabel.frame = innerView.bounds; + [innerView addSubview:innerLabel]; + + SQSpriteView *spriteView = [SQSpriteView new]; + spriteView.matchRect = [innerView.superview convertRect:innerView.frame toView:self.view]; + spriteView.backgroundColor = [UIColor systemGreenColor]; + NSString *address = [NSString stringWithFormat:@"%p", spriteView]; + dict[address] = @(NO); + + spriteView.matching = ^(SQSpriteView *matchView) { + if (matchView.isMatch) { + matchView.matched = YES; + dict[address] = @(YES); + } + BOOL successed = YES; + for (NSNumber *num in dict.allValues) { + if (!num.boolValue) { + successed = NO; + } + } + if (successed) { + NSLog(@"游戏通关"); + } + }; + + CGFloat movableViewX = arc4random() % (int)(self.view.bounds.size.width - movableViewW); + CGFloat movableViewY = arc4random() % (int)(self.view.bounds.size.height - movableViewH); + spriteView.frame = CGRectMake(movableViewX, movableViewY, movableViewW, movableViewH); + [self.view addSubview:spriteView]; + + UILabel *movableLabel = [UILabel new]; + movableLabel.text = innerLabel.text; + movableLabel.textAlignment = innerLabel.textAlignment; + movableLabel.font = innerLabel.font; + movableLabel.frame = spriteView.bounds; + [spriteView addSubview:movableLabel]; + } + } + return self; +} + +@end diff --git a/SQNumber/SQNumber/SQSceneView.h b/SQNumber/SQNumber/SQSceneView.h new file mode 100644 index 00000000..16e181a7 --- /dev/null +++ b/SQNumber/SQNumber/SQSceneView.h @@ -0,0 +1,21 @@ +// +// SQSceneView.h +// SQNumber +// +// Created by 朱双泉 on 2020/9/11. +// Copyright © 2020 朱双泉. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface SQSceneView : UIView + +@property (nonatomic, assign) NSUInteger capacity; + +- (void)renderToCanvas:(UIView *)superView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SQNumber/SQNumber/SQSceneView.m b/SQNumber/SQNumber/SQSceneView.m new file mode 100644 index 00000000..544c89f7 --- /dev/null +++ b/SQNumber/SQNumber/SQSceneView.m @@ -0,0 +1,84 @@ +// +// SQSceneView.m +// SQNumber +// +// Created by 朱双泉 on 2020/9/11. +// Copyright © 2020 朱双泉. All rights reserved. +// + +#import "SQSceneView.h" +#import "SQSpriteView.h" + +@implementation SQSceneView + +- (void)renderToCanvas:(UIView *)superView { + [superView addSubview:self]; + + NSInteger capacity = self.capacity ? self.capacity : 3; + NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:capacity]; + + UIView *containerView = [UIView new]; + CGFloat containerViewW = self.bounds.size.width * 0.9; + CGFloat containerViewH = containerViewW * 0.2; + CGFloat containerViewX = (self.bounds.size.width - containerViewW) * 0.5; + CGFloat containerViewY = (self.bounds.size.height - containerViewH) * 0.5; + containerView.frame = CGRectMake(containerViewX, containerViewY, containerViewW, containerViewH); + [self addSubview:containerView]; + + CGFloat innerViewW = containerViewH - 20; + CGFloat innerViewH = innerViewW; + CGFloat innerViewY = (containerViewH - innerViewH) * 0.5; + CGFloat innerViewS = (containerViewW - (innerViewW * capacity)) / (capacity + 1); + CGFloat movableViewW = innerViewW - 20; + CGFloat movableViewH = movableViewW; + for (NSInteger i = 0; i < capacity; i++) { + UIView *innerView = [UIView new]; + CGFloat innerViewX = innerViewS + (i * (innerViewW + innerViewS)); + innerView.backgroundColor = [UIColor lightGrayColor]; + innerView.frame = CGRectMake(innerViewX, innerViewY, innerViewW, innerViewH); + [containerView addSubview:innerView]; + + UILabel *innerLabel = [UILabel new]; + innerLabel.text = @(i + 1).stringValue; + innerLabel.textAlignment = NSTextAlignmentCenter; + innerLabel.font = [UIFont boldSystemFontOfSize:120]; + innerLabel.frame = innerView.bounds; + [innerView addSubview:innerLabel]; + + SQSpriteView *spriteView = [SQSpriteView new]; + spriteView.matchRect = [innerView.superview convertRect:innerView.frame toView:self]; + spriteView.backgroundColor = [UIColor systemGreenColor]; + NSString *address = [NSString stringWithFormat:@"%p", spriteView]; + dict[address] = @(NO); + + spriteView.matching = ^(SQSpriteView *matchView) { + if (matchView.isMatch) { + matchView.matched = YES; + dict[address] = @(YES); + } + BOOL successed = YES; + for (NSNumber *num in dict.allValues) { + if (!num.boolValue) { + successed = NO; + } + } + if (successed) { + NSLog(@"游戏通关"); + } + }; + + CGFloat movableViewX = arc4random() % (int)(self.bounds.size.width - movableViewW); + CGFloat movableViewY = arc4random() % (int)(self.bounds.size.height - movableViewH); + spriteView.frame = CGRectMake(movableViewX, movableViewY, movableViewW, movableViewH); + [self addSubview:spriteView]; + + UILabel *movableLabel = [UILabel new]; + movableLabel.text = innerLabel.text; + movableLabel.textAlignment = innerLabel.textAlignment; + movableLabel.font = innerLabel.font; + movableLabel.frame = spriteView.bounds; + [spriteView addSubview:movableLabel]; + } +} + +@end diff --git a/SQNumber/SQNumber/SQSpriteView.m b/SQNumber/SQNumber/SQSpriteView.m index b923a145..6ad40e60 100755 --- a/SQNumber/SQNumber/SQSpriteView.m +++ b/SQNumber/SQNumber/SQSpriteView.m @@ -6,25 +6,34 @@ // #import "SQSpriteView.h" -#import "SQTimer.h" @interface SQSpriteView () -@property (nonatomic, copy) NSString *directionTimerId; -@property (nonatomic, copy) NSString *frameTimerId; +@property (nonatomic, strong) NSTimer *directionTimer; +@property (nonatomic, strong) NSTimer *frameTimer; @end @implementation SQSpriteView +- (void)dealloc { + [self clearTimer]; +} + - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { - [self updateCoordinate]; + [self performSelector:@selector(updateCoordinate) + withObject:nil afterDelay:(arc4random() % 3)]; } return self; } +- (void)clearTimer { + [self.directionTimer invalidate]; + [self.frameTimer invalidate]; +} + typedef NS_ENUM(NSUInteger, SQSpriteDirection) { SQSpriteDirectionNone = 0, SQSpriteDirectionUp, @@ -39,11 +48,12 @@ typedef NS_ENUM(NSUInteger, SQSpriteDirection) { - (void)updateCoordinate { __block NSInteger direction = 0; - - self.directionTimerId = [SQTimer execTask:^{ + + self.directionTimer = [NSTimer scheduledTimerWithTimeInterval:2 repeats:YES block:^(NSTimer * _Nonnull timer) { direction = arc4random() % 9; - } start:0 interval:2 repeats:YES async:NO]; - self.frameTimerId = [SQTimer execTask:^{ + }]; + + self.frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.03 repeats:YES block:^(NSTimer * _Nonnull timer) { CGRect frame = self.frame; switch (direction) { case SQSpriteDirectionNone: @@ -91,12 +101,7 @@ - (void)updateCoordinate { } else if (self.frame.origin.y + self.bounds.size.height + margin >= self.superview.bounds.size.height) { direction = SQSpriteDirectionUp; } - } start:0 interval:0.03 repeats:YES async:NO]; -} - -- (void)clearTimer { - [SQTimer cancelTask:self.directionTimerId]; - [SQTimer cancelTask:self.frameTimerId]; + }]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { @@ -105,6 +110,8 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { if (self.matched) return; + [self.superview bringSubviewToFront:self]; + UITouch * touch = [touches anyObject]; CGPoint current = [touch locationInView:self]; CGPoint previous = [touch previousLocationInView:self]; @@ -128,6 +135,7 @@ - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { _match = CGRectContainsRect(self.matchRect, self.frame); if (self.isMatch) { + [self.superview sendSubviewToBack:self]; [self clearTimer]; } else { [self updateCoordinate]; diff --git a/SQNumber/SQNumber/SQTimer.h b/SQNumber/SQNumber/SQTimer.h deleted file mode 100644 index 17696fcf..00000000 --- a/SQNumber/SQNumber/SQTimer.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// SQTimer.h -// 12-内存管理 -// -// Created by 朱双泉 on 2019/5/22. -// Copyright © 2019 Castie!. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface SQTimer : NSObject - -+ (NSString *)execTask:(void(^)(void))task - start:(NSTimeInterval)start - interval:(NSTimeInterval)interval - repeats:(BOOL)repeats - async:(BOOL)async; - -+ (NSString *)execTask:(id)target - selector:(SEL)selector - start:(NSTimeInterval)start - interval:(NSTimeInterval)interval - repeats:(BOOL)repeats - async:(BOOL)async; - -+ (void)cancelTask:(NSString *)name; - -@end - -NS_ASSUME_NONNULL_END diff --git a/SQNumber/SQNumber/SQTimer.m b/SQNumber/SQNumber/SQTimer.m deleted file mode 100644 index dc470ca8..00000000 --- a/SQNumber/SQNumber/SQTimer.m +++ /dev/null @@ -1,89 +0,0 @@ -// -// SQTimer.m -// 12-内存管理 -// -// Created by 朱双泉 on 2019/5/22. -// Copyright © 2019 Castie!. All rights reserved. -// - -#import "SQTimer.h" - -@implementation SQTimer - -static NSMutableDictionary *timers_; -dispatch_semaphore_t semaphore_; -+ (void)initialize { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - timers_ = [NSMutableDictionary dictionary]; - semaphore_ = dispatch_semaphore_create(1); - }); -} - -+ (NSString *)execTask:(void (^)(void))task start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async { - - if (!task || start < 0 || (interval <= 0 && repeats)) return nil; - - // 队列 - dispatch_queue_t queue = async ? dispatch_get_global_queue(0, 0) - : dispatch_get_main_queue(); - - // 创建定时器 - dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); - - // 设置时间 - dispatch_source_set_timer(timer, - dispatch_time(DISPATCH_TIME_NOW, start * NSEC_PER_SEC), - interval * NSEC_PER_SEC, 0); - - dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER); - - // 定时器的唯一标识 - NSString *name = [NSString stringWithFormat:@"%zd", timers_.count]; - // 存放到字典中 - timers_[name] = timer; - - dispatch_semaphore_signal(semaphore_); - - // 设置回调 - dispatch_source_set_event_handler(timer, ^{ - task(); - - if (!repeats) { // 不重复的任务 - [self cancelTask:name]; - } - }); - - // 启动定时器 - dispatch_resume(timer); - - return name; -} - -+ (NSString *)execTask:(id)target selector:(SEL)selector start:(NSTimeInterval)start interval:(NSTimeInterval)interval repeats:(BOOL)repeats async:(BOOL)async { - if (!target || !selector) return nil; - return [self execTask:^{ - if ([target respondsToSelector:selector]) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" - [target performSelector:selector]; -#pragma clang diagnostic pop - } - } start:start interval:interval repeats:repeats async:async]; -} - -+ (void)cancelTask:(NSString *)name { - if (name.length == 0) return; - - dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER); - - dispatch_source_t timer = timers_[name]; - if (timer) { - dispatch_source_cancel(timer); - [timers_ removeObjectForKey:name]; - } - - dispatch_semaphore_signal(semaphore_); -} - -@end diff --git a/SQNumber/SQNumber/ViewController.m b/SQNumber/SQNumber/ViewController.m index 5c63c468..77b0ac57 100644 --- a/SQNumber/SQNumber/ViewController.m +++ b/SQNumber/SQNumber/ViewController.m @@ -7,7 +7,7 @@ // #import "ViewController.h" -#import "SQSpriteView.h" +#import "SQSceneView.h" @interface ViewController () @@ -18,72 +18,9 @@ @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; - NSInteger count = 2; - NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:count]; - - UIView *containerView = [UIView new]; - CGFloat containerViewW = self.view.bounds.size.width * 0.9; - CGFloat containerViewH = containerViewW * 0.2; - CGFloat containerViewX = (self.view.bounds.size.width - containerViewW) * 0.5; - CGFloat containerViewY = (self.view.bounds.size.height - containerViewH) * 0.5; - containerView.frame = CGRectMake(containerViewX, containerViewY, containerViewW, containerViewH); - [self.view addSubview:containerView]; - - CGFloat innerViewW = containerViewH - 20; - CGFloat innerViewH = innerViewW; - CGFloat innerViewY = (containerViewH - innerViewH) * 0.5; - CGFloat innerViewS = (containerViewW - (innerViewW * count)) / (count + 1); - CGFloat movableViewW = innerViewW - 20; - CGFloat movableViewH = movableViewW; - for (NSInteger i = 0; i < count; i++) { - UIView *innerView = [UIView new]; - innerView.tag = i + 1; - CGFloat innerViewX = innerViewS + (i * (innerViewW + innerViewS)); - innerView.backgroundColor = [UIColor lightGrayColor]; - innerView.frame = CGRectMake(innerViewX, innerViewY, innerViewW, innerViewH); - [containerView addSubview:innerView]; - - UILabel *innerLabel = [UILabel new]; - innerLabel.text = @(innerView.tag).stringValue; - innerLabel.textAlignment = NSTextAlignmentCenter; - innerLabel.font = [UIFont boldSystemFontOfSize:120]; - innerLabel.frame = innerView.bounds; - [innerView addSubview:innerLabel]; - - SQSpriteView *movableView = [SQSpriteView new]; - movableView.matchRect = [innerView.superview convertRect:innerView.frame toView:self.view]; - movableView.backgroundColor = [UIColor systemGreenColor]; - NSString *address = [NSString stringWithFormat:@"%p", movableView]; - dict[address] = @(NO); - - movableView.matching = ^(SQSpriteView *matchView) { - if (matchView.isMatch) { - matchView.matched = YES; - dict[address] = @(YES); - } - BOOL successed = YES; - for (NSNumber *num in dict.allValues) { - if (!num.boolValue) { - successed = NO; - } - } - if (successed) { - NSLog(@"游戏通关"); - } - }; - - CGFloat movableViewX = arc4random() % (int)(self.view.bounds.size.width - movableViewW); - CGFloat movableViewY = arc4random() % (int)(self.view.bounds.size.height - movableViewH); - movableView.frame = CGRectMake(movableViewX, movableViewY, movableViewW, movableViewH); - [self.view addSubview:movableView]; - - UILabel *movableLabel = [UILabel new]; - movableLabel.text = innerLabel.text; - movableLabel.textAlignment = innerLabel.textAlignment; - movableLabel.font = innerLabel.font; - movableLabel.frame = movableView.bounds; - [movableView addSubview:movableLabel]; - } + SQSceneView *sceneView = [SQSceneView new]; + sceneView.frame = self.view.bounds; + [sceneView renderToCanvas:self.view]; }