উত্তর:
3.0 এ, এখন আরও সহজ উপায় - নতুন গতির ইভেন্টগুলিতে হুক।
মূল কৌশলটি হ'ল আপনার কিছু ইউআইভিউ (ইউআইভিউ কনট্রোলার নয়) থাকা দরকার যা আপনি কাঁপানো ইভেন্ট বার্তাগুলি পেতে ফার্স্ট রিসপন্ডার হিসাবে চান। কাঁপানো ইভেন্টগুলি পেতে আপনি যে কোনও ইউআইভিউতে এই কোডটি ব্যবহার করতে পারেন:
@implementation ShakingView
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if ( event.subtype == UIEventSubtypeMotionShake )
{
// Put in code here to handle shake
}
if ( [super respondsToSelector:@selector(motionEnded:withEvent:)] )
[super motionEnded:motion withEvent:event];
}
- (BOOL)canBecomeFirstResponder
{ return YES; }
@end
আপনি যে কোনও ইউআইভিউ (এমনকি সিস্টেম ভিউ) সহজেই এমন একটি দৃশ্যে রূপান্তর করতে পারেন যা কেবলমাত্র এই পদ্ধতিগুলির সাহায্যে ভিউ উপশ্রুত করে (এবং তারপরে আইবিতে বেস ধরণের পরিবর্তে এই নতুন প্রকারটি নির্বাচন করে, বা বরাদ্দকালে এটি ব্যবহার করে) এমন দৃশ্যে রূপান্তর করতে পারে দৃশ্য)।
ভিউ কন্ট্রোলারে, আপনি এই দর্শনটি প্রথম প্রতিক্রিয়াশীল হিসাবে সেট করতে চান:
- (void) viewWillAppear:(BOOL)animated
{
[shakeView becomeFirstResponder];
[super viewWillAppear:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
[shakeView resignFirstResponder];
[super viewWillDisappear:animated];
}
ভুলে যাবেন না যে যদি আপনার অন্যান্য মতামতগুলি ব্যবহারকারীর ক্রিয়া থেকে প্রথম প্রতিক্রিয়াশীল হয়ে থাকে (যেমন কোনও অনুসন্ধান বার বা পাঠ্য প্রবেশের ক্ষেত্র) তবে অন্য দৃষ্টিভঙ্গি পদত্যাগ করার সময় আপনাকে কাঁপানো দৃশ্যের প্রথম প্রতিক্রিয়াশীল স্থিতি পুনরুদ্ধার করতে হবে!
আপনি যদি অ্যাপ্লিকেশনসপোর্টস শেকটওএডিটকে NO তে সেট করেন এমনকি এই পদ্ধতিটি কাজ করে।
motionEnded
কারণ আইকনটি আসলে প্রকট বন্ধ হওয়ার আগেই গুলি চালানো পছন্দ করে । সুতরাং এই পদ্ধতির সাহায্যে আপনি একটি দীর্ঘ একের পরিবর্তে সংক্ষিপ্ত শেকসগুলির একটি বিশৃঙ্খল সিরিজ পান। অন্য উত্তর এই ক্ষেত্রে অনেক ভাল কাজ করে।
[super respondsToSelector:
আপনি যা চান তা করবেন না, কারণ এটি কল করার সমতুল্য [self respondsToSelector:
যা ফিরে আসবে YES
। আপনার যা দরকার তা হ'ল [[ShakingView superclass] instancesRespondToSelector:
।
আমার ডিসিশেকার অ্যাপ্লিকেশন থেকে:
// Ensures the shake is strong enough on at least two axes before declaring it a shake.
// "Strong enough" means "greater than a client-supplied threshold" in G's.
static BOOL L0AccelerationIsShaking(UIAcceleration* last, UIAcceleration* current, double threshold) {
double
deltaX = fabs(last.x - current.x),
deltaY = fabs(last.y - current.y),
deltaZ = fabs(last.z - current.z);
return
(deltaX > threshold && deltaY > threshold) ||
(deltaX > threshold && deltaZ > threshold) ||
(deltaY > threshold && deltaZ > threshold);
}
@interface L0AppDelegate : NSObject <UIApplicationDelegate> {
BOOL histeresisExcited;
UIAcceleration* lastAcceleration;
}
@property(retain) UIAcceleration* lastAcceleration;
@end
@implementation L0AppDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[UIAccelerometer sharedAccelerometer].delegate = self;
}
- (void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
if (self.lastAcceleration) {
if (!histeresisExcited && L0AccelerationIsShaking(self.lastAcceleration, acceleration, 0.7)) {
histeresisExcited = YES;
/* SHAKE DETECTED. DO HERE WHAT YOU WANT. */
} else if (histeresisExcited && !L0AccelerationIsShaking(self.lastAcceleration, acceleration, 0.2)) {
histeresisExcited = NO;
}
}
self.lastAcceleration = acceleration;
}
// and proper @synthesize and -dealloc boilerplate code
@end
হিস্টেরেসিস শেক ইভেন্টটিকে একাধিকবার ট্রিগার করা থেকে বিরত রাখে যতক্ষণ না ব্যবহারকারী ঝাঁকুনি থামায়।
motionBegan
এবং motionEnded
ইভেন্টগুলি শেকের সঠিক শুরু এবং শেষ সনাক্তকরণের ক্ষেত্রে খুব সুনির্দিষ্ট বা সঠিক নয়। এই পদ্ধতির সাহায্যে আপনি চান হিসাবে সুনির্দিষ্ট হতে পারবেন।
শেষ পর্যন্ত আমি এটিকে পূর্বাবস্থায় ফেরানো / রিডো ম্যানেজার টিউটোরিয়াল থেকে কোড উদাহরণ ব্যবহার করে এটি কাজ করে ফেলি ।
আপনার ঠিক এটি করা দরকার:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
application.applicationSupportsShakeToEdit = YES;
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
-(BOOL)canBecomeFirstResponder {
return YES;
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self becomeFirstResponder];
}
- (void)viewWillDisappear:(BOOL)animated {
[self resignFirstResponder];
[super viewWillDisappear:animated];
}
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (motion == UIEventSubtypeMotionShake)
{
// your code
}
}
applicationSupportsShakeToEdit
হয় YES
।
[self resignFirstResponder];
সামনে ফোন কেন [super viewWillDisappear:animated];
? এটি অদ্ভুত বলে মনে হচ্ছে।
প্রথমত, কেন্ডালের 10 ই জুলাইয়ের উত্তরটি স্পট-অন।
এখন ... আমি অনুরূপ কিছু করতে চেয়েছিলাম (আইফোন ওএস 3.0.০+ এ), কেবলমাত্র আমার ক্ষেত্রে আমি এটি অ্যাপ্লিকেশনই চেয়েছিলাম যাতে কোনও কাঁপুনি লাগলে আমি অ্যাপের বিভিন্ন অংশকে সতর্ক করতে পারি । এখানে আমি শেষ করতে পেরেছি।
প্রথমত, আমি ইউআইওয়াইন্ডো সাবক্লাস করেছি । এটি সহজ স্বাচ্ছন্দ্য। একটি ইন্টারফেসের সাথে একটি নতুন শ্রেণীর ফাইল তৈরি করুন MotionWindow : UIWindow
(নিজের পছন্দ চয়ন করুন, ন্যাচ করুন)। এর মতো একটি পদ্ধতি যুক্ত করুন:
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
if (event.type == UIEventTypeMotion && event.subtype == UIEventSubtypeMotionShake) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"DeviceShaken" object:self];
}
}
@"DeviceShaken"
আপনার পছন্দের বিজ্ঞপ্তি নাম পরিবর্তন করুন। ফাইলটি সংরক্ষণ করুন।
এখন, আপনি একটি MainWindow.xib (স্টক Xcode টেমপ্লেট কাপড়) ব্যবহার, সেখানে গিয়ে থেকে আপনার উইন্ডো বস্তুর শ্রেণী পরিবর্তন UIWindow করার MotionWindow বা যাই হোক না কেন আপনি এটা বলা হয়। Xib সংরক্ষণ করুন। আপনি যদি প্রোগ্রামটিমেটিকভাবে ইউআইওয়াইন্ডো সেট আপ করেন তবে পরিবর্তে সেখানে আপনার নতুন উইন্ডো ক্লাসটি ব্যবহার করুন।
এখন আপনার অ্যাপ্লিকেশনটি বিশেষায়িত ইউআই উইন্ডো ক্লাস ব্যবহার করছে । যেখানেই আপনাকে কাঁপানোর বিষয়ে বলা যেতে চাই, তাদের বিজ্ঞপ্তিগুলির জন্য সাইন আপ করুন! এটার মত:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(deviceShaken) name:@"DeviceShaken" object:nil];
নিজেকে পর্যবেক্ষক হিসাবে অপসারণ করতে:
[[NSNotificationCenter defaultCenter] removeObserver:self];
আমি আমার ভিউউইল অ্যাপয়ারে রাখি: এবং ভিউইলডিস্পায়ার: যেখানে ভিউ কন্ট্রোলাররা উদ্বিগ্ন। শেক ইভেন্টে আপনার প্রতিক্রিয়াটি এটি "ইতিমধ্যে চলছে" কিনা তা নিশ্চিত হয়ে নিন। অন্যথায়, যদি ডিভাইসটি পর পর দু'বার কাঁপানো হয় তবে আপনার কাছে ট্র্যাফিক জ্যাম লাগবে। আপনি যখনই সত্যিকারের মূল বিজ্ঞপ্তির প্রতিক্রিয়াটি সম্পন্ন না করেন ততক্ষণ আপনি অন্যান্য বিজ্ঞপ্তিগুলি উপেক্ষা করতে পারবেন।
এছাড়াও: আপনি মোশনবেগান বনাম গতিবেগের বন্ধ করে দেওয়া বেছে নিতে পারেন । এটা আপনার উপর নির্ভর করছে. আমার ক্ষেত্রে, ডিভাইসটি বিশ্রাম নেওয়ার পরে সর্বদা প্রভাবটি হওয়া দরকার (বনাম যখন এটি কাঁপানো শুরু হয়), তাই আমি মোশনএন্ডড ব্যবহার করি । উভয়ই চেষ্টা করে দেখুন এবং কোনটি আরও বেশি বোঝায় তা দেখুন ... বা উভয়ের জন্য সনাক্ত / অবহিত করুন!
এখানে আরও একটি (কৌতূহলী?) পর্যবেক্ষণ: লক্ষ্য করুন যে এই কোডটিতে প্রথম উত্তরদাতা পরিচালনার কোনও চিহ্ন নেই। আমি এ পর্যন্ত কেবল টেবিল ভিউ কন্ট্রোলার দিয়ে এটি চেষ্টা করেছি এবং সবকিছু একসাথে বেশ সুন্দরভাবে কাজ করছে বলে মনে হচ্ছে! যদিও আমি অন্যান্য পরিস্থিতিতে সন্ধান করতে পারি না।
কেন্ডাল, ইত্যাদি। আল - কেউ ইউআই উইন্ডো সাবক্লাসের জন্য কেন এমন হতে পারে তা বলতে পারে ? এটি কি কারণ উইন্ডোটি খাদ্য শৃঙ্খলের শীর্ষে রয়েছে?
আমি একটি "কাঁপানো" বাস্তবায়ন সন্ধানে এই পোস্টটি জুড়ে এসেছি। সহস্রাব্দের উত্তর আমার পক্ষে ভাল কাজ করেছে, যদিও আমি এমন কিছু সন্ধান করছিলাম যা ট্রিগার করতে আরও কিছুটা "কাঁপানো ক্রিয়া" দরকার। আমি একটি ইন্ট শেককাউন্টের সাথে বুলিয়ান মানকে প্রতিস্থাপন করেছি। আমি উদ্দেশ্য-সি-তে L0AclaysrationIsShaking () পদ্ধতিটি পুনরায় প্রয়োগ করেছি imp শ্যাককাউন্টে যুক্ত হওয়া পরিমাণটি টুইট করে আপনি ঝাঁকুনির পরিমাণটি সাম্যস্থ করতে পারেন। আমি নিশ্চিত নই যে আমি এখনও সর্বোত্তম মানগুলি খুঁজে পেয়েছি তবে এটি এখনও পর্যন্ত ভালভাবে কাজ করছে বলে মনে হচ্ছে। আশা করি এটি কাউকে সহায়তা করবে:
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
if (self.lastAcceleration) {
if ([self AccelerationIsShakingLast:self.lastAcceleration current:acceleration threshold:0.7] && shakeCount >= 9) {
//Shaking here, DO stuff.
shakeCount = 0;
} else if ([self AccelerationIsShakingLast:self.lastAcceleration current:acceleration threshold:0.7]) {
shakeCount = shakeCount + 5;
}else if (![self AccelerationIsShakingLast:self.lastAcceleration current:acceleration threshold:0.2]) {
if (shakeCount > 0) {
shakeCount--;
}
}
}
self.lastAcceleration = acceleration;
}
- (BOOL) AccelerationIsShakingLast:(UIAcceleration *)last current:(UIAcceleration *)current threshold:(double)threshold {
double
deltaX = fabs(last.x - current.x),
deltaY = fabs(last.y - current.y),
deltaZ = fabs(last.z - current.z);
return
(deltaX > threshold && deltaY > threshold) ||
(deltaX > threshold && deltaZ > threshold) ||
(deltaY > threshold && deltaZ > threshold);
}
PS: আমি আপডেটের ব্যবধানটি সেকেন্ডের 1/15 তমতে সেট করে রেখেছি।
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / 15)];
অ্যাক্সিলোমিটারের মাধ্যমে আপনাকে অ্যাক্সিলোমিটারটি পরীক্ষা করতে হবে: ডিএ অ্যাক্সিলারেট: পদ্ধতিটি যা ইউআইএসিক্রেরোমিটারডেলিগেট প্রোটোকলের অংশ এবং এটি পরীক্ষা করতে পারে যে মানগুলি একটি ঝাঁকুনির জন্য প্রয়োজনীয় গতিবিধির জন্য একটি প্রান্তিকের ওপরে যায় কিনা।
অ্যাক্সিলোমিটারে শালীন নমুনা কোড রয়েছে: জিএলপেন্ট উদাহরণে AppController.m এর নীচে ঠিক পদ্ধতি যা আইফোন বিকাশকারী সাইটে উপলব্ধ।
আইওএস 8.3 এ (সম্ভবত এর আগে) সুইফট সহ, এটি আপনার ভিউ কন্ট্রোলারে থাকা পদ্ধতি motionBegan
বা motionEnded
পদ্ধতিগুলিকে ওভাররাইড করার মতোই সহজ :
class ViewController: UIViewController {
override func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent) {
println("started shaking!")
}
override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent) {
println("ended shaking!")
}
}
এটি আপনার প্রয়োজনীয় বেসিক প্রতিনিধি কোড:
#define kAccelerationThreshold 2.2
#pragma mark -
#pragma mark UIAccelerometerDelegate Methods
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
if (fabsf(acceleration.x) > kAccelerationThreshold || fabsf(acceleration.y) > kAccelerationThreshold || fabsf(acceleration.z) > kAccelerationThreshold)
[self myShakeMethodGoesHere];
}
ইন্টারফেসে উপযুক্ত কোডে সেট করুন। অর্থাৎ,
@ ইনটারফেস মাইভিউকন্ট্রোলার: ইউআইভিউউকন্ট্রোলার <ইউআইআইপিকার ভিউডেলিগেট, ইউআইপিকারিকার ভিউডাটা সোর্স, ইউআইএসিক্রেরোমিটারডেলিগেট>
জিএলপেন্ট উদাহরণ দেখুন Check
http://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html
ViewController.m ফাইলটিতে নিম্নলিখিত পদ্ধতিগুলি যুক্ত করুন, এটি সঠিকভাবে কাজ করছে
-(BOOL) canBecomeFirstResponder
{
/* Here, We want our view (not viewcontroller) as first responder
to receive shake event message */
return YES;
}
-(void) motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if(event.subtype==UIEventSubtypeMotionShake)
{
// Code at shake event
UIAlertView *alert=[[UIAlertView alloc] initWithTitle:@"Motion" message:@"Phone Vibrate"delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
[alert release];
[self.view setBackgroundColor:[UIColor redColor]];
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self becomeFirstResponder]; // View as first responder
}
একটি মন্তব্য না করে উত্তর হিসাবে পোস্ট করার জন্য দুঃখিত তবে আপনি দেখতে পাচ্ছেন আমি স্ট্যাক ওভারফ্লোতে নতুন এবং তাই আমি এখনও মন্তব্য পোস্ট করার মতো যথেষ্ট নামী নন!
যাইহোক আমি দ্বিতীয় বারের মতামতটি ভিউয়ের ক্রমবিন্যাসের অংশ হয়ে গেলে প্রথম প্রতিক্রিয়াশীল স্থিতি সেট করা নিশ্চিত করার বিষয়ে কায়ার করছি। সুতরাং আপনার দৃশ্য নিয়ন্ত্রণকারী viewDidLoad
পদ্ধতিতে প্রথম প্রতিক্রিয়াশীল স্থিতি স্থাপন করা উদাহরণস্বরূপ কাজ করবে না। এবং যদি আপনি অনিশ্চিত হন যে এটি কাজ করছে কিনা [view becomeFirstResponder]
আপনাকে পরীক্ষা করতে পারে এমন একটি বুলিয়ান দেয়।
আরেকটি বিষয়: আপনি অযথা ইউআইভিউ সাবক্লাস তৈরি করতে না চাইলে আপনি শেক ইভেন্টটি ক্যাপচার করতে একটি ভিউ কন্ট্রোলার ব্যবহার করতে পারেন। আমি জানি এটি তেমন ঝামেলা নয় তবে এখনও বিকল্প রয়েছে। কেন্ডাল ইউআইভিউ সাবক্লাসে আপনার নিয়ামকের মধ্যে রেখে দেওয়া কোড স্নিপেটগুলি সরিয়ে ফেলুন এবং ইউআইভিউ সাবক্লাসের পরিবর্তে becomeFirstResponder
এবং resignFirstResponder
বার্তা প্রেরণ করুন self
।
প্রথমত, আমি জানি এটি একটি পুরানো পোস্ট, তবে এটি এখনও প্রাসঙ্গিক এবং আমি দেখতে পেয়েছি যে দুটি সর্বোচ্চ ভোট দেওয়া উত্তর খুব শীঘ্রই শেক সনাক্ত করতে পারেনি । এটি এটি করতে হয়:
আপনার ভিউকন্ট্রোলারে:
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (motion == UIEventSubtypeMotionShake) {
// Shake detected.
}
}
আপনার অ্যাপ্লিকেশনটির জন্য একটি নতুন মূল উইন্ডো আহরণ করা সবচেয়ে সহজ সমাধান:
@implementation OMGWindow : UIWindow
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
if (event.type == UIEventTypeMotion && motion == UIEventSubtypeMotionShake) {
// via notification or something
}
}
@end
তারপরে আপনার আবেদনের প্রতিনিধিটিতে:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[OMGWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
//…
}
আপনি যদি স্টোরিবোর্ড ব্যবহার করে থাকেন তবে এটি কৌতুকপূর্ণ হতে পারে, আপনি অবশ্যই অ্যাপ্লিকেশন প্রতিনিধিটিতে যে কোডটি প্রয়োজন হবে তা আমি জানি না।
@implementation
এটি করার জন্য এই তিনটি পদ্ধতি ব্যবহার করুন
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event{
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{
বিস্তারিত জানার জন্য তোমাদের উপর সম্পূর্ণ উদাহরণ কোড চেক করতে পারেন সেখানে
খুব প্রথম উত্তরটির উপর ভিত্তি করে একটি সুইফটিজ সংস্করণ!
override func motionEnded(_ motion: UIEventSubtype, with event: UIEvent?) {
if ( event?.subtype == .motionShake )
{
print("stop shaking me!")
}
}
এই অ্যাপ্লিকেশন-বিস্তৃত সক্ষম করতে, আমি UIWindow এ একটি বিভাগ তৈরি করেছি:
@implementation UIWindow (Utils)
- (BOOL)canBecomeFirstResponder
{
return YES;
}
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (motion == UIEventSubtypeMotionShake) {
// Do whatever you want here...
}
}
@end
viewDidAppear
পরিবর্তে আমার কন্ট্রোলারের ওভাররাইড করা দরকারviewWillAppear
। আমি নিশ্চিত না কেন; শেক ইভেন্টগুলি গ্রহণ শুরু করতে এটি যা কিছু করতে পারে তার আগেই দৃশ্যটি দৃশ্যমান হওয়া দরকার?