我最近添加了线程到应用程序,以便网络请求不会阻止UI.在这样做时,我发现我无法再像实现线程之前那样设置我的实例变量.我的实例变量是一个声明如下的属性:
@property (nonatomic, strong) NSMutableArray *currentTopPlaces;
Run Code Online (Sandbox Code Playgroud)
以下是我错误地设置我的实例变量self.currentTopPlaces的方法:
dispatch_queue_t downloadQueue = dispatch_queue_create("Flickr Top Places Downloader", NULL);
dispatch_async(downloadQueue, ^{
__block NSArray *topPlaces = [FlickrFetcher topPlaces];
dispatch_async(dispatch_get_main_queue(), ^{
self.tableRowCount = [topPlaces count];
[[self currentTopPlaces] setArray:topPlaces];
});
Run Code Online (Sandbox Code Playgroud)
在我开始使用GCD之前,使用[self currentTopPlace] setArray:topPlaces]在阻止版本中运行良好.
现在,为了让事情正常工作,我必须这样设置:
dispatch_queue_t downloadQueue = dispatch_queue_create("Flickr Top Places Downloader", NULL);
dispatch_async(downloadQueue, ^{
__block NSArray *topPlaces = [FlickrFetcher topPlaces];
dispatch_async(dispatch_get_main_queue(), ^{
self.tableRowCount = [topPlaces count];
self.currentTopPlaces = topPlaces;
});
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释使用之间的区别:
[[self currentTopPlaces] setArray:topPlaces];
Run Code Online (Sandbox Code Playgroud)
和:
self.currentTopPlaces = topPlaces;
Run Code Online (Sandbox Code Playgroud)
具体来说,为什么"setArray"调用在线程块中不起作用?
我认为Objective-C中的点符号是语法糖而不是强制性的.我想知道实现相同行为的"非加糖"方式.
我有一个方法应该返回一个填充在后台线程中的数组.我想等待return语句,直到数组完全填充.我该怎么办?我知道如何处理没有返回类型的数据,但我想调用此函数并获取填充的数组.
示例(此处数组结束为空,因为它在填充数组之前返回 - 我想做一些事情来返回填充的数组):
-(NSArray*)fetchSomeArray{
__block NSArray *arrayToReturn;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,(unsigned long)NULL), ^(void) {
NSArray *someArray = ...; // getting some array from database
arrayToReturn = [NSMutableArray new];
for(int i=0;i<someArray.count;i++){
[arrayToReturn addObject:...];
}
});
return arrayToReturn;
}
Run Code Online (Sandbox Code Playgroud) 嗨!
我正在使用GCD构建一个计时器,以便以特定的间隔播放声音,更准确地说,它是一个节拍器声音.我一直在努力解决我的问题,但没有.一切都很好但是当我把我的节奏设置为更大的值时,让我们说150 bpm或200 bpm,当声音第一次开始时,它会很快发射(几乎像两个声音在同一时间意味着它没有预期间隔)并在此之后,它进行校准.我第二次启动声音,一切都很好......所以这只发生在我第一次恢复调度源时所以我猜它与从磁盘加载声音有关,就像在这篇帖子中一样:慢第一次播放声音时启动AVAudioPlayer.对于我的声音我在第一次的实例中使用AVAudioPlayer与prepareToPlay并且play还在AppDelegate类中创建它,它还没有工作......我甚至尝试过@NickLockwood开发的SoundManager类,同样的问题.目前,我正在使用SystemSoundID.至于计时器,这是我的第一个GCD计时器,我已经尝试了经典的NSTimer,CADisplayLink以及在git上找到的其他计时器...都是徒劳的.
另一个有趣的问题是,与其他计时器一样,在模拟器上一切都很完美,但在设备上却出现了同样的故障.
这是代码,我希望有人能把我带到光明之中.
-(void)playButtonAction //
{
if (_metronomeIsAnimatingAndPLaying == NO)
{
[self startAnimatingArm]; // I start my animation and create my timer
metronomeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
dispatch_source_set_timer(metronomeTimer,dispatch_time(DISPATCH_TIME_NOW, duration * NSEC_PER_SEC),duration * NSEC_PER_SEC,duration *NSEC_PER_SEC);
dispatch_source_set_event_handler(metronomeTimer, ^{[self playTick];});
dispatch_resume(metronomeTimer);
_metronomeIsAnimatingAndPLaying = YES;
}
}
-(void)playTick
{
AudioServicesPlaySystemSound(appDeleg.soundID); // soundID is created in appDelegate
}
Run Code Online (Sandbox Code Playgroud)
在我的应用程序didFinishLaunching
NSString *path = [[NSBundle mainBundle] pathForResource:@"tick"
ofType:@"caf"]; …Run Code Online (Sandbox Code Playgroud) 我正在努力dispatch_group和dispatch_group_notify,在所有任务完成之前调用.我试图做的是迭代一些查询,获取它们,并将返回的XML处理成CoreData实体.然后,当一切都完成后,我调用上下文保存所有数据到商店.但是dispatch_group_notify在所有任务完成之前调用,并且没有任何保存.
这是一些代码:
dispatch_group_t dispatchGroup = dispatch_group_create();
for (NSString *query in queryArray)
{
dispatch_group_enter(dispatchGroup);
NSLog(@"enter");
[myDownloadClient searchForQuery: query
withParameters: nil
completion: ^(NSData *data, NSError *error) {
[self processXML: data];
NSLog(@"end import");
}];
NSLog(@"leave");
dispatch_group_leave(dispatchGroup);
}
dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(),^{
NSLog(@"save");
[self saveContext];
}
Run Code Online (Sandbox Code Playgroud)
我在日志中看到的是
enter
leave
enter
leave
...
save
end import
...
Run Code Online (Sandbox Code Playgroud)
如您所见,在完成所有下载和XML处理之前会显示save,因此无需保存.
我怎样才能让它发挥作用?
根据苹果指南,为了在主线程上使用托管对象,它们需要由仅限于主线程的上下文获取,好的,没关系。下面是我的代码...
AppDelegate *del = [[UIApplication sharedApplication] delegate];
dispatch_queue_t queue1 = dispatch_queue_create("com.MyApp.AppTask",NULL);
dispatch_queue_t main = dispatch_get_main_queue();
dispatch_async(queue1, ^{
NSManagedObjectContext *workerContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
workerContext.persistentStoreCoordinator = del.persistentStoreCoordinator;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Person"];
NSArray *managedObject = [workerContext executeFetchRequest:fetchRequest error:nil];
dispatch_async(main, ^{
NSLog(@"%@",managedObject);
Person *objperson = [managedObject objectAtIndex:0];
objperson.firstname = @“test”;
BOOL s = [workerContext save:nil];
if (s) {
NSLog(@"done");
}
});
});
Run Code Online (Sandbox Code Playgroud)
现在根据指南,我无法修改或保存由另一个线程创建的托管对象上下文。但上面的代码工作正常,修改和保存我的对象没有任何错误。因此,我可以修改由另一个线程获取的 MO,甚至可以保存由另一个线程创建的 MOC。
请让我知道我这样做的方式是否错误,因为理想情况下我无法从主线程保存后台线程的 MOC。
谢谢你。
我有一个用Swift编写的函数.我希望完成块返回一个布尔值.我该怎么做呢?我正在使用Grand Central Dispatch.
func myFunc() -> Bool
{
var success:Bool = false
// code here
dispatch_async(dispatch_get_main_queue(), {
return success
)}
)}
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
我正在尝试加载一个巨大的图像(谈论131.072x131.072像素)很好地平铺成一堆URL的256x256像素的512x512块.
一旦我的函数返回Image我想在一个正确位置的Rect中绘制它.
由于这个过程需要一段时间,我想以异步方式运行整个过程.以下是我到目前为止所尝试的内容:
override func drawRect(rect: CGRect) {
let firstColumn = Int(CGRectGetMinX(rect) / sideLength)
let lastColumn = Int(CGRectGetMaxX(rect) / sideLength)
let firstRow = Int(CGRectGetMinY(rect) / sideLength)
let lastRow = Int(CGRectGetMaxY(rect) / sideLength)
let qos = Int(QOS_CLASS_USER_INITIATED.rawValue)
dispatch_async(dispatch_get_global_queue(qos, 0)) { () -> Void in
for row in firstRow...lastRow {
for column in firstColumn...lastColumn {
let url = NSURL(string: "https://someURL/\(row)/\(column).jpg")
let tile = UIImage(data: NSData(contentsOfURL: url!)!)!
let x = self.sideLength * CGFloat(column)
let y = self.sideLength * CGFloat(row)
let point = CGPoint(x: …Run Code Online (Sandbox Code Playgroud) 首先我使用 arc4random 创建了一个 randomDelay 值
然后我想将 randomDelay 值添加到 DispatchQueue 以创建一个随机时间延迟变量
这是我的代码:
func animation1() {
UIView.animate(withDuration: 1, animations: {
// various code
}, completion: { (true) in
//delay calling the function by the randomDelay value of '0' to '2' seconds
let randomDelay = arc4random_uniform(3)
DispatchQueue.main.asyncAfter(deadline: .now() + randomDelay) { // the randomDelay value throws an unresolved identifier 'randomDelay' error
self.showAnimation2() // Go to the next function
}
})
}
Run Code Online (Sandbox Code Playgroud)
谢谢
我正在处理一些旧代码。以下是我无法转换或理解的两行(旧代码):
let dispatchTime = dispatch_time(dispatch_time_t(DispatchTime.now()), Int64(seconds * Double(NSEC_PER_SEC)))
dispatch_after(dispatchTime, dispatch_get_main_queue(), block)
Run Code Online (Sandbox Code Playgroud)
现在,为了让它在Swift 4.x 中工作,这就是我为第 1 行所做的:
let dispatchTime = DispatchTime(uptimeNanoseconds: UInt64(Int64(seconds * Double(NSEC_PER_SEC))))
Run Code Online (Sandbox Code Playgroud)
我根据此处提到的初始化程序描述进行了此转换:
创建一个相对于系统时钟的时间,自启动以来滴答作响。
既然他们说它创建了一个相对时间,DispatchTime.now()就已经考虑过了。更不用说,我可能是错的。请纠正我。
对于第二行,我不知道如何DispatchTime在DispatchAfter.
我正在尝试使用 CoreImage & Metal 处理一系列 UIImages 并显示它们。我的问题是如果我的 gcd 块很忙,我想删除传入的图像。我如何实现这个 GCD 队列,我如何定义队列的最大缓冲区大小?
ios ×9
swift ×5
core-data ×2
asynchronous ×1
audio ×1
concurrency ×1
core-audio ×1
core-image ×1
ios5 ×1
metal ×1
objective-c ×1
timing ×1
xcode ×1