Objective c 为什么不是';在这个实现中是否有多线程工作?
Q1:我可以调用一个方法并让它从当前在主线程上执行的另一个方法中在后台线程上执行吗 问题2:作为上述方法的扩展,我是否可以调用一个方法并让它从另一个方法内部在后台线程上执行,该方法当前正在其他后台线程上执行 问题3:上面给出的最后一个问题是:如果我在某个线程(main/background)上初始化某个对象X的实例,然后在另一个后台线程上执行该对象X的一个方法Y,那么该方法Y是否可以发送消息并更新Objective c 为什么不是';在这个实现中是否有多线程工作?,objective-c,ios,multithreading,Objective C,Ios,Multithreading,Q1:我可以调用一个方法并让它从当前在主线程上执行的另一个方法中在后台线程上执行吗 问题2:作为上述方法的扩展,我是否可以调用一个方法并让它从另一个方法内部在后台线程上执行,该方法当前正在其他后台线程上执行 问题3:上面给出的最后一个问题是:如果我在某个线程(main/background)上初始化某个对象X的实例,然后在另一个后台线程上执行该对象X的一个方法Y,那么该方法Y是否可以发送消息并更新int属性(例如,该对象X的通信,或该通信是否不可能 我问最后一个问题的原因是因为我已经一遍又一遍地
int属性
(例如,该对象X的通信,或该通信是否不可能
我问最后一个问题的原因是因为我已经一遍又一遍地问了,我不知道这里出了什么问题:
以下代码返回零加速度和零度值:
MotionHandler.m
@implementation MotionHandler
@synthesize currentAccelerationOnYaxis; // this is a double
-(void)startCompassUpdates
{
locationManager=[[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate=self;
[locationManager startUpdatingHeading];
NSLog(@"compass updates initialized");
}
-(int) currentDegrees
{
return (int)locationManager.heading.magneticHeading;
}
-(void) startAccelerationUpdates
{
CMMotionManager *motionManager = [[CMMotionManager alloc] init];
motionManager.deviceMotionUpdateInterval = 0.01;
[motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler:^(CMDeviceMotion *motion, NSError *error)
{
self.currentAccelerationOnYaxis = motion.userAcceleration.y;
}
];
}
@end
测试员
@implementation Tester
-(void)test
{
MotionHandler *currentMotionHandler = [[MotionHandler alloc] init];
[currentMotionHandler performSelectorInBackground:@selector(startCompassUpdates) withObject:nil];
[currentMotionHandler performSelectorInBackground:@selector(startAccelerationUpdates) withObject:nil];
while(1==1)
{
NSLog(@"current acceleration is %f", currentMotionHandler.currentAccelerationOnYaxis);
NSLog(@"current degrees are %i", [currentMotionHandler currentDegrees]);
}
@interface Tester()
{
CLLocationManager *locationManager;
double accelerationOnYaxis;
// more code..
}
@end
@implementation Tester
- (id) init
{
locationManager=[[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate=self;
[locationManager startUpdatingHeading];
// more code..
}
-(void) test
{
CMMotionManager *motionManager = [[CMMotionManager alloc] init];
motionManager.deviceMotionUpdateInterval = 0.01;
[motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMDeviceMotion *motion, NSError *error)
{
accelerationOnYaxis = motion.userAcceleration.y;
}
];
while(1==1)
{
NSLog(@"current acceleration is %f", accelerationOnYaxis);
NSLog(@"current degrees are %i", locationManager.heading.magneticHeading);
}
}
SomeViewController.m
@implementation SomeViewController
-(void) viewDidLoad
{
[myTester performSelectorInBackground:@selector(test) withObject:nil];
}
@end
@implementation SomeViewController
-(void) viewDidLoad
{
[myTester performSelectorInBackground:@selector(test) withObject:nil];
}
但是,以下代码通常返回这些值:
测试员
@implementation Tester
-(void)test
{
MotionHandler *currentMotionHandler = [[MotionHandler alloc] init];
[currentMotionHandler performSelectorInBackground:@selector(startCompassUpdates) withObject:nil];
[currentMotionHandler performSelectorInBackground:@selector(startAccelerationUpdates) withObject:nil];
while(1==1)
{
NSLog(@"current acceleration is %f", currentMotionHandler.currentAccelerationOnYaxis);
NSLog(@"current degrees are %i", [currentMotionHandler currentDegrees]);
}
@interface Tester()
{
CLLocationManager *locationManager;
double accelerationOnYaxis;
// more code..
}
@end
@implementation Tester
- (id) init
{
locationManager=[[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate=self;
[locationManager startUpdatingHeading];
// more code..
}
-(void) test
{
CMMotionManager *motionManager = [[CMMotionManager alloc] init];
motionManager.deviceMotionUpdateInterval = 0.01;
[motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMDeviceMotion *motion, NSError *error)
{
accelerationOnYaxis = motion.userAcceleration.y;
}
];
while(1==1)
{
NSLog(@"current acceleration is %f", accelerationOnYaxis);
NSLog(@"current degrees are %i", locationManager.heading.magneticHeading);
}
}
SomeViewController.m
@implementation SomeViewController
-(void) viewDidLoad
{
[myTester performSelectorInBackground:@selector(test) withObject:nil];
}
@end
@implementation SomeViewController
-(void) viewDidLoad
{
[myTester performSelectorInBackground:@selector(test) withObject:nil];
}
第一个版本有什么问题?我真的很想使用第一个版本,因为它在设计方面似乎更好。谢谢您的帮助!调用
性能选择器背景:withObject:
与使用当前对象、选择器和参数对象作为参数。无论您在哪里调用它,都将创建一个新线程来执行该选择器。因此,请回答前两个问题:是和是
对于最后一个问题,只要这个对象X在两种方法中都是同一个对象,X的任何属性都可以更新。但是,请注意,这可能会产生意外的结果(例如,请参阅)。如果有多个方法正在更新X的属性,则可以覆盖或忽略值。但是,如果您仅从方法Y更新属性并从所有其他方法读取属性,则不应出现此类问题。您应该查看。它允许您在基于块的结构中使用多个线程 两个重要的函数是
dispatch\u sync()
和dispatch\u async()
一些例子:
要在后台线程上执行特定代码块并等待它完成,请执行以下操作:
__block id someVariable = nil;
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
// do some heavy work in the background
someVariable = [[NSObject alloc] init];
});
NSLog(@"Variable: %@", someVariable);
此函数修改变量someVariable,您可以稍后使用。请注意,主线程将暂停以等待后台线程。如果这不是您想要的,您可以使用dispatch\u async()
,如下所示:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
// do some heavy work in the background
NSObject *someVariable = [[NSObject alloc] init];
// notify main thread that the work is done
dispatch_async(dispatch_get_main_queue(), ^{
// call some function and pass someVariable to it, it will be called on the main thread
NSLog(@"Variable: %@", someVariable);
});
});
请查看我的编辑,以更好地了解我的问题是什么您是否尝试调试了新代码?如果您已经有了一个工作版本,它应该足够简单,可以在已更改的代码上设置一些断点,并找出出现了什么问题。我们已经回答了您最初的问题;现在由您来回答这些问题将其应用于您的特定问题。对于初学者,我看到您正在背对背调用
startCompassUpdate
和startAccelerationUpdate
,每个线程都在单独的线程中。您确定指南针和加速更新在无限while循环之前已初始化吗?我已在不同的点使用NSLog进行了检查,显然是协同的MPAS和加速更新在第二个版本中从未初始化,但我不知道为什么。感谢您回答我的3个问题。在实际实施您的建议之前,我现在必须返回并尝试找出第二个版本不起作用的原因。再次感谢!我决定发布另一个问题以避免c如果你感兴趣的话。。