我有一个内存错误,似乎归结为一个线程中发生的事情.我在排除故障时遇到了困难.
我有一个UIViewController,当它处于活动状态时,即用户正在使用其视图时,从NSThread中的Web服务检索更新.
这是每3分钟完成一次,这个延迟由以下控制:
[self performSelector:@selector(timerDone) withObject:nil afterDelay:180.0];
Run Code Online (Sandbox Code Playgroud)
该timerDone方法现在启动NSThread,它检索Web服务数据,并performSelector再次发送消息.这有点"检查更新,填充视图,关闭所有内容,重复"例程,工作得很好.
现在,用户当然可以突然点击一个按钮加载第二个UIViewController.当这发生时,我打电话给:
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(timerDone) object:nil];
Run Code Online (Sandbox Code Playgroud)
并在dealloc方法中进行清理.
我现在的问题是:如果NSThread正在运行,而用户更改了视图并启动了对象的解构,这是NSThread的起点,会发生什么?
我应该保持一个BOOL,告诉我NSThread是否仍然有效,如果是,那么如果是这样的话,如何处理NSThread.
线程是这样完成的:
- (void) runTimer {
[self performSelector:@selector(timerDone) withObject:nil afterDelay:180];
}
- (void) timerDone {
[self performSelector:@selector(runTimer) withObject:nil afterDelay:2];
[NSThread detachNewThreadSelector:@selector(updateAllVisibleElements) toTarget:self withObject:nil];
}
- (void) updateAllVisibleElements {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//call approiate web service
[pool release];
}
Run Code Online (Sandbox Code Playgroud) 我的应用程序中有一些Web服务数据需要每3分钟更新一次.我曾尝试过一些方法,但上周在这里得到了一个非常好的建议,我不应该每隔3分钟建立一个新线程然后尝试dealloc并同步所有不同的部分,以便我避免内存错误.相反,我应该有一个始终在运行的"工作线程",但只在我提出要求时才进行实际工作(每3分钟一次).
正如我的小POC现在一样,我在applicationDidFinishLaunching
方法中生成了一个新线程.我是这样做的:
[NSThread detachNewThreadSelector:@selector(updateModel) toTarget:self withObject:nil];
- (void) updateModel {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
BackgroundUpdate *update = [[BackgroundUpdate alloc] initWithTimerInterval:180];
[update release];
[pool release];
}
Run Code Online (Sandbox Code Playgroud)
好的,这会在"BackgroundUpdate"对象中以更新间隔(以秒为单位).在更新程序内部,它现在就像这样:
@implementation BackgroundUpdate
- (id) initWithTimerInterval:(NSInteger) secondsBetweenUpdates {
if(self = [super init]) {
[NSTimer scheduledTimerWithTimeInterval:secondsBetweenUpdates
target:self
selector:@selector(testIfUpdateNeeded)
userInfo:nil
repeats:YES];
}
return self;
}
- (void) testIfUpdateNeeded {
NSLog(@"Im contemplating an update...");
}
Run Code Online (Sandbox Code Playgroud)
我之前从未使用过这样的线程.我一直都是"设置autoReleasePool,做好工作,让你的autoReleasePool耗尽,再见".
我的问题是,一旦initWithTimerInterval运行NSThread完毕,它就会返回到updateModel方法并将其池耗尽.我想这与NSTimer有自己的线程/ runloop有关吗?我想让线程继续testIfUpdateNeeded每隔3分钟运行一次方法.
那么如何在我的应用程序的整个过程中保持这个NSThread活着?
感谢您给予的任何帮助/建议:)
我有一个很大的问题,因为我无法解决几天.
首先,我有一个使用此代码的登录视图控制器:
@implementation MMConnectionViewController
@synthesize login, password, activityIndicator, mainVC;
- (BOOL)textFieldShouldReturn:(UITextField *)aTextField
{
[aTextField resignFirstResponder];
[self performSelectorOnMainThread:@selector(startRolling) withObject:nil waitUntilDone:NO];
[NSThread detachNewThreadSelector:@selector(connect) toTarget:self withObject:nil];
return YES;
}
- (void)viewWillAppear:(BOOL)flag {
[super viewWillAppear:flag];
[login becomeFirstResponder];
login.keyboardAppearance = UIKeyboardAppearanceAlert;
password.keyboardAppearance = UIKeyboardAppearanceAlert;
[self setTitle:@"Monaco Marine"];
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Logout"
style:UIBarButtonItemStyleBordered
target:nil
action:nil];
self.navigationItem.backBarButtonItem = backBarButtonItem;
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque];
[backBarButtonItem release];
}
- (void)connect {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
mainVC = [[MMMainViewController alloc] initWithLogin:login.text password:password.text connectPass:@"1" navigationController:self.navigationController nibName:@"MMMainViewController" …Run Code Online (Sandbox Code Playgroud) 我正在使用performSelector执行动画:withObject:afterDelay at 24fps.
(原因是,UIImageView不支持图像之间的不同间隔)
当我同时运行多个动画时,看起来像performselector排队的消息需要很长时间才能被拾取.
我想知道NSTimer还是另一个会是更好的选择.
谢谢
除了运行动画之外我什么也没做.
我正在运行的选择器占用0.0003的时间.(几乎没有时间)
但是当我测量调用"performSelector"和选择器实际被调用的时间之间的时间时,实际上比我用"afterDelay"或" scheduledTimerWithDuration"
我已经查看了仪器,但无法弄清楚导致延迟的原因.
我刚刚看到线程相关(我猜线程暂停/恢复)活动很多.
也许我的下面的threadMain代码占用了很多时间?
- (void) myThreadMain
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
// Add your sources or timers to the run loop and do any other setup.
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
[runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
do
{
// Start the run loop but return after each source is handled.
SInt32 result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, YES);
}
while (self.isNeedToExit == false);
[pool release];
SYSLOG(LOG_DEBUG, "thread exiting");
}
Run Code Online (Sandbox Code Playgroud) 这两者有什么不同?
[NSThread detachNewThreadSelector:@selector(method) toTarget:self withObject:nil];
[self performSelectorInBackground:@selector(method) withObject:nil];
Run Code Online (Sandbox Code Playgroud)
我通常使用第二种方法来生成一个新线程.但是我想知道如果我将这两次调用如下所示,那么将会发生什么?另外如果我有一个tabmenu并且每个菜单产生一个线程,那么我应该使用哪一个?
[self performSelectorInBackground:@selector(method1) withObject:nil];
[self performSelectorInBackground:@selector(method2) withObject:nil];
Run Code Online (Sandbox Code Playgroud) 我开始使用GCD了,我需要知道某个线程何时结束了它的工作.
我的代码:
dispatch_queue_t registerDeviceQueue = dispatch_queue_create("RegisterDevice", NULL);
dispatch_async(registerDeviceQueue, ^{
[self registerDevice];
dispatch_async(dispatch_get_main_queue(), ^{
[aiRegisterDevice stopAnimating];
});
});
dispatch_release(registerDeviceQueue);
Run Code Online (Sandbox Code Playgroud)
我需要知道这个步骤何时结束,以便UIActivityView可以停止.它现在的方式,它在线程结束前停止.
谢谢,
RL
我正在开发一个应用程序,我需要从一个线程中截取屏幕截图.我无法使用以下代码执行此操作:
UIGraphicsBeginImageContextWithOptions(self.view.frame.size, YES, [[UIScreen mainScreen] scale]);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Run Code Online (Sandbox Code Playgroud)
如果有人要将此问题标记为重复,那么请提供一个正确的链接来回答并请关注此问题我也在询问有关在线程中创建图像的问题.
谢谢你的时间.
如果我像这样存储dispatch_queue_t:
@property(assign, nonatomic) dispatch_queue_t myQueue;
Run Code Online (Sandbox Code Playgroud)
...
_myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
Run Code Online (Sandbox Code Playgroud)
后来,当我做手术时
dispatch_async(_myQueue, ^{
NSLog(@"Hi!");
});
Run Code Online (Sandbox Code Playgroud)
然后在其他地方
dispatch_async(_myQueue, ^{
NSLog(@"Hello!");
});
Run Code Online (Sandbox Code Playgroud)
这些块是在同一个线程上执行的吗?如果没有,我该如何确保它们?基本上我想保留对线程的引用,并使其仅在该线程上执行某些操作.
multithreading nsthread grand-central-dispatch ios objective-c-blocks
在我的主要启动线程中,我需要暂停代码并启动一个新线程并等待我收到用户输入.然后我想丢弃新的线程并返回到主线程停止的位置.但最新发生的是调用新线程,但主线程继续使用代码.如何在不干扰用户使用界面按钮的情况下处理此问题?我认为可能在我的if(moveCount == 2)语句中需要另一个nscondition?或者我的主线程需要等待来自我的其他线程的信号通知用户输入被接收.
附加注意:我也希望原始线程暂停,这样我仍然可以在界面中使用我的2个UIButton.
有关收到的问题的更多补充说明:这是我正在制作的游戏.在代码中间代码在我的主要线程中意味着我的一个方法.这个方法决定我在哪个方向移动,然后我得到一个标签差异,然后进行攻击.但有时可以进行2次攻击,因此此时用户可以通过2个按钮点击屏幕来决定要进行哪次攻击.
我也很安静地告诉我,我现在不应该暂停主线程.如果是这样,替代方案是什么?谢谢
NSCondition和NSThread
@property (strong, nonatomic) NSCondition *condition;
@property (strong, nonatomic) NSThread *aThread;
Run Code Online (Sandbox Code Playgroud)
在我的viewDidLoad中创建以下内容.
// create the NSCondition instance
self.condition = [[NSCondition alloc]init];
// create the thread
self.aThread = [[NSThread alloc] initWithTarget:self selector:@selector(threadLoop) object:nil];
Run Code Online (Sandbox Code Playgroud)
代码中间的某个地方..
if(moveCount == 2){
[self.aThread start];
}
// I need to get captureDecision from user from 2 buttons before continue.. How do I pause this thread when aThread is started. Then when capture decision is received discard aThread and start here.
NSLog(@"Capture …Run Code Online (Sandbox Code Playgroud) 如果我分离NSThread将Cocoa运行在一个单独的内存堆或内存区域?例如,如果我要分离一个线程,使用malloc创建一个大缓冲区,然后让线程退出,我会在某种自动线程清理中恢复该内存,还是会被泄露?
如果我使用POSIX线程(pthread)呢?
请注意,我对ObjC allocs或autorelease pool不感兴趣,我说的是低级缓冲区,例如int*foo = malloc(100000);
我在代码的这一部分有一些随机崩溃:
-(void) goBack {
[self performSelectorInBackground:@selector(addActivityIndicator) withObject:nil];
[self.navigationController popViewControllerAnimated:YES];
}
- (void)addActivityIndicator {
@autoreleasepool {
UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
UIBarButtonItem * barButton = [[UIBarButtonItem alloc] initWithCustomView:activityView];
[activityView startAnimating];
self.navigationItem.leftBarButtonItem = barButton;
}
}
Run Code Online (Sandbox Code Playgroud)
当我想退出存在这些方法的屏幕时,另一个ViewController必须处理一些数据.为了通知用户正在进行处理,我在导航栏的左侧按钮中添加了一个活动指示器.
问题是有时候我会得到一个exc_bad_accessin addActivityIndicator方法.频率非常随机,有时XCode @autoreleasepool会在结束时显示错误,有时候会显示错误self.navigationItem.leftBarButtonItem = barButton;
我想有时我的viewController被销毁但是线程仍在运行并尝试访问不再存在的对象的navigationItem.但我不确定这是不是问题,我不知道如何解决它.
我在我的项目中使用ARC,这个问题出现在我测试的所有iOS版本中.
拜托,任何人都可以向我解释发生了什么,我该如何解决这个问题?
谢谢.
在运行我的线程一段时间后,Instruments表明__NSDate已经稳定地修改了它的#vide值.
我的结论是,这个步骤不会处理对象.但是,这一行导致编译错误NSAutoreleasePool*pool = [[NSAutoreleasePool alloc] init];
如何强制此线程保留其所有对象,或者如何使用工作ARC创建正确的线程.
- (void) start {
NSThread* myThread = [[NSThread alloc] initWithTarget:self
selector:@selector(myThreadMainRoutine)
object:nil];
[myThread start]; // Actually create the thread
}
- (void)myThreadMainRoutine {
// stuff inits here ...
// Do thread work here.
while (_live) {
// do some stuff ...
[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.05]];
[NSThread sleepForTimeInterval:0.05f];
}
// clean stuff here ...
}
Run Code Online (Sandbox Code Playgroud) multithreading objective-c nsthread ios automatic-ref-counting