I am using OpenTok Framework and it cause crash when my app goes to background and foreground multiple times. May be it is due to memory loss but i have tried on instrument and enabled zombie objects and malloc guard but nothing helps me out.
Here are few of my crash listing from Crashlytics.
1).
webrtc::StatsReport::Value* std::__uninitialized_copy_aux<__gnu_cxx::__normal_iterator<webrtc::StatsReport::Value const*, std::vector<webrtc::StatsReport::Value, std::allocator<webrtc::StatsReport::Value> > >, webrtc::StatsReport::Value*>(__gnu_cxx::__normal_iterator<webrtc::StatsReport::Value const*, std::vector<webrtc::StatsReport::Value, std::allocator<webrtc::StatsReport::Value> > >, __gnu_cxx::__normal_iterator<webrtc::StatsReport::Value const*, std::vector<webrtc::StatsReport::Value, std::allocator<webrtc::StatsReport::Value> > >, webrtc::StatsReport::Value*, std::__false_type)
2).
AudioToolbox
AUIOHelper::NotifyInputAvailable(AudioTimeStamp const&, unsigned long, AudioBufferList const&)
The way i am using openTok library is:
- (void)doConnect
{
// Create a session to the doctor.
_mySession = [[OTSession alloc] initWithSessionId:self.doctor.sessionId
delegate:self];
// Connect the session created to the doctor.
[_mySession connectWithApiKey:kApiKey token:self.doctor.token];
}
- (void)doPublish
{
// Create a publisher.
_publisher = [[OTPublisher alloc] initWithDelegate:self name:UIDevice.currentDevice.name];
[_publisher.view.toolbarView setHidden:NO];
[_publisher.view.toolbarView setAlpha:1.0];
// Publish user's stream to the connected session.
[_mySession publish:_publisher];
// Show user's stream in bottom-right corner.
CGRect frame = CGRectMake(self.view.frame.size.width - mySize.width, self.view.frame.size.height - mySize.height - 50, mySize.width, mySize.height);
_publisherView = _publisher.view;
[_publisherView setFrame:CGRectInset(frame, 10, 10)];
[self.cameraView addSubview:_publisherView];
}
pragma mark - OTSessionDelegate Methods
- (void)sessionDidConnect:(OTSession*)session
{
[self doPublish];
}
- (void)session:(OTSession*)mySession didReceiveStream:(OTStream*)stream
{
if (![stream.connection.connectionId isEqualToString:_mySession.connection.connectionId])
{
[self doSubscribeToStream:stream];
}
}
- (void)doSubscribeToStream:(OTStream *)stream
{
self.lblDoctorName.text = self.doctor.name;
if (!_subscriber) {
_subscriber = [[OTSubscriber alloc] initWithStream:stream delegate:self];
}
}
Can any one help me out in these crashes ?
There were some crashing issues in the iOS SDK on OpenTok. There was a big iOS SDK release a few days ago that addresses the crashing and should fix your issue: http://tokbox.com/opentok/libraries/client/ios/
Related
I've setup my AVAudioEngine in its own method like this:
AVAudioSession* session = [AVAudioSession sharedInstance];
[session setPreferredSampleRate:[session sampleRate] error:nil];
[session setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
[session setActive:YES error:nil];
audioEngine_ = [[AVAudioEngine alloc] init];
//tap the outputNode to create the singleton
[audioEngine_ outputNode];
NSError* error;
[audioEngine_ startAndReturnError:&error];
There is no error starting it up. I have another method to attach an AVAudioUnitMIDIInstrument from an AudioComponentDescription I've received from an Inter-App Audio instrument. My connect method looks like this:
-(void)connectInstrument:(AudioComponentDescription)desc {
instNode_ = nil;
instNode_ = [[AVAudioUnitMIDIInstrument alloc] initWithAudioComponentDescription:desc];
[audioEngine_ attachNode:instNode_];
//Crashes here
[audioEngine_ connect:instNode_ to:[audioEngine_ outputNode] format:nil];
[audioEngine_ startAndReturnError:nil];
NSLog(#"done connecting");
}
The crash gives me no useful information. I get this:
invalid mode 'kCFRunLoopCommonModes' provided to CFRunLoopRunSpecific - break on _CFRunLoopError_RunCalledWithInvalidMode to debug. This message will only appear once per execution.
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndexedSubscript:]: index 0 beyond bounds for empty array'
If I do a test and try to create a new mixer node and attach/connect it, there is no crash.
I have more relevant information
If I do this:
AVAudioFormat* instFormat = [instUnit_ outputFormatForBus:0];
I get the same error:
-[__NSArrayM objectAtIndexedSubscript:]: index 0 beyond bounds for empty array
It's almost as though there is no AVAudioFormat set for any output busses, nor any input busses (I checked inputFormatForBus as well). This is odd because if I do:
AudioStreamBasicDescription f1;
UInt32 outsize = sizeof(f1);
AudioUnitGetProperty(instNode_.audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &f1, &outsize);
Then f1 is a valid AudioStreamBasicDescription showing a standard 44.1khz sample rate, 32 bit float, 2 channels. So there is an output stream format, but it doesn't seem to be attached to any output bus of the AVAudioUnitMIDIInstrument instance.
EDIT - Further information
Even if I just try to access instUnite_.name I get the NSRangeException. I'm wondering now if this is a problem with how I'm getting the component description. I'm attempting to use Inter-App Audio (I have done all of the proper entitlements, capabilities, and app ID setup). This is how I am discovering Inter-App Audio components:
NSMutableArray* units = [[NSMutableArray alloc] init];
AudioComponentDescription searchDesc = { kAudioUnitType_RemoteInstrument, 0, 0, 0, 0 };
NSArray* componentArray = [[AVAudioUnitComponentManager sharedAudioUnitComponentManager] componentsMatchingDescription:searchDesc];
for(AVAudioUnitComponent* component in componentArray) {
AudioComponentDescription description = component.audioComponentDescription;
InterAppAudioUnit* unit = [[InterAppAudioUnit alloc] init];
unit.componentDescription = description;
unit.icon = AudioComponentGetIcon(component.audioComponent, 44.0f);
unit.name = component.name;
unit.avComponent = component;
[units addObject:unit];
}
_units = units;
[self.tableView reloadData];
This is all in a presented UITableViewController. After clicking one I simply execute:
[self connectInstrument:unit.componentDescription];
If I instead hand build a component description for a local unit, the AVAudioUnit is instantiated just fine and nothing crashes.
I found the answer. The AUAudioUnit object inside of the AVAudioUnit object has no output busses upon creation. I'm not sure why. You can fix it by doing this:
AUAudioUnit* auInst = instUnit_.AUAudioUnit;
NSMutableArray<AUAudioUnitBus*>* busArray = [[NSMutableArray alloc] init];
AVAudioFormat* outFormat = [[self->audioEngine_ outputNode] outputFormatForBus:0];
AUAudioUnitBus* bus = [[AUAudioUnitBus alloc] initWithFormat:outFormat error:&err];
[busArrays addObject:bus];
[[auInst outputBusses] replaceBusses:busArray];
I'm using Spotify iOS SDK beta 6 and trying to get a list of the tracks i've saved.
There is a getSavedTracks method that I'm trying to call:
[self getSavedTracks:(SPTSavedTrack *__autoreleasing *) range:(NSRange)]
And the same method I'm trying to implement:
-(void)getSavedTracks:(object-type **)buffer range:(NSRange)inRange
Right now, I'm at a lost as to what to put in the parameters. I'm thinking this for the implementation?
-(void)getSavedTracks:(SPTSavedTrack **)buffer range:(NSRange)inRange {
[SPTRequest savedTracksForUserInSession:self.session callback:^(NSError error, SPTSavedTrack trackObjects) {
if (error != nil) {
NSLog(#"*** Enabling playback got error: %#", error);
return;
}
self.savedTracks = [[NSMutableArray alloc]initWithObjects:trackObjects, nil];
}];
}
There's nothing in their SDK API reference that mention this method. Thanks
The methods you're talking about don't exist in the SDK.
You need SPTRequest's +savedTracksForUserInSession:callback: method. Like this:
[SPTRequest savedTracksForUserInSession:session callback:^(NSError *error, id object) {
// Object contains the `SPTListPage` containing the first page of saved tracks
}];
I'm launching a localization request using Grand Central Dispatch :
- (void) findGroceriesNearMe {
dispatch_queue_t downloadQueue = dispatch_queue_create("Groceries downloader", NULL);
dispatch_async(downloadQueue, ^{
CLLocationCoordinate2D userLocation = [LocationManagerController findMeWithCaller:self];
dispatch_async(dispatch_get_main_queue(), ^{
[self userSuccessFullyFound:userLocation];
});
});
dispatch_release(downloadQueue);
}
It calls a static method in my Singleton class LocationManager Controller :
+ (CLLocationCoordinate2D) findMeWithCaller: (UIViewController *) viewController {
LocationManagerController *locationManagerController = [LocationManagerController locationManagerController];
[locationManagerController startUpdates];
while(![locationManagerController getterDone]){
//mystique pour nous-- a approfondir
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
In the startUpdates method, the CLLocationManager, property of LocationManagerController, is initialized and asked to startUpdatingLocation.
Finally, the method when location updates happen :
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
locationDenied = NO;
NSLog(#"%f,%f",newLocation.coordinate.latitude,newLocation.coordinate.longitude);
NSDate* eventDate = newLocation.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
// On vérifie que la newLocation est récente
if (abs(howRecent) > 10.0) {
return;
}
// Test if it's not an invalid measurement
if (newLocation.horizontalAccuracy < 0) return;
// Test the measurement to see if it meets the desired accuracy
if (newLocation.horizontalAccuracy <= manager.desiredAccuracy)
{
latitude = newLocation.coordinate.latitude;
longitude = newLocation.coordinate.longitude;
locationDefined = YES;
[self setterDone:YES];
}
}
My problem is that the locationManager only send 3 location updates and then stops sending updates even though I didn't ask it to stop. So basically, I never get out of the while(![locationManagerController getterDone]) loop.
By the way, before trying to implement this using GCD, it was working fine so I guess the issue has to do with my implementation of multi-threading.
Any idea ?
Edit
I don't get any error in the console. The program just keeps running but I'm stuck in that while loop and nothing else happens after the 3 first location updates.
Thanks !
From CLLocationManager class reference:
Configuration of your location manager object must always occur on a
thread with an active run loop, such as your application’s main
thread.
A guess. If you are sitting at your desk and testing with your simulator the accuracy may not get better what you want
if (newLocation.horizontalAccuracy <= manager.desiredAccuracy)
So you may get stuck in your loop. Try with higher accuracy while at your desk. Also consider if the accuracy is never better that what you want since it maybe that the gps reception is not good.
Let me know if that helps or if I was way off the mark :-)
-- Fasttouch
Background
I've got the following tree of objects:
Name Project
Users nil
John nil
Documents nil
Acme Project Acme Project <--- User selects a project
Proposal.doc Acme Project
12:32-12:33 Acme Project
13:11-13:33 Acme Project
...thousands more entries here...
The user can assign a group to a project. All descendants get set to that project.
This locks up the main thread so I'm using NSOperations.
I'm using the Apple approved way of doing this, watching for NSManagedObjectContextDidSaveNotification and merging into the main context.
The Problem
My saves have been failing with the following error:
Failed to process pending changes before save. The context is still dirty after 100 attempts. Typically this recursive dirtying is caused by a bad validation method, -willSave, or notification handler.
What I've Tried
I've stripped all the complexities of my app away, and made the simplest project I could think of. And the error still occurs. I've tried:
Setting the max number of operations on the queue to 1 or 10.
Calling refreshObject:mergeChanges: at several points in the NSOperation subclass.
Setting merge policies on the managed object context.
Build and Analyze. It comes up empty.
My Question
How do I set relationships in an NSOperation without my app crashing? Surely this can't be a limitation of Core Data? Can it?
The Code
Download my project: http://synapticmishap.co.uk/CDMTTest1.zip
Main Controller
#implementation JGMainController
-(IBAction)startTest:(id)sender {
NSManagedObjectContext *imoc = [[NSApp delegate] managedObjectContext];
JGProject *newProject = [JGProject insertInManagedObjectContext:imoc];
[newProject setProjectName:#"Project"];
[imoc save];
// Make an Operation Queue
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue setMaxConcurrentOperationCount:1]; // Also crashes with a higher number here (unsurprisingly)
NSSet *allTrainingGroupsSet = [imoc fetchAllObjectsForEntityName:#"TrainingGroup"];
for(JGTrainingGroup *thisTrainingGroup in allTrainingGroupsSet) {
JGMakeRelationship *makeRelationshipOperation = [[JGMakeRelationship alloc] trainGroup:[thisTrainingGroup objectID] withProject:[newProject objectID]];
[queue addOperation:makeRelationshipOperation];
makeRelationshipOperation = nil;
}
}
// Called on app launch.
-(void)setupLotsOfTestData {
// Sets up 10000 groups and one project
}
#end
Make Relationship Operation
#implementation JGMakeRelationshipOperation
-(id)trainGroup:(NSManagedObjectID *)groupObjectID_ withProject:(NSManagedObjectID *)projectObjectID_ {
appDelegate = [NSApp delegate];
imoc = [[NSManagedObjectContext alloc] init];
[imoc setPersistentStoreCoordinator:[appDelegate persistentStoreCoordinator]];
[imoc setUndoManager:nil];
[imoc setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification
object:imoc];
groupObjectID = groupObjectID_;
projectObjectID = projectObjectID_;
return self;
}
-(void)main {
JGProject *project = (JGProject *)[imoc objectWithID:projectObjectID];
JGTrainingGroup *trainingGroup = (JGTrainingGroup *)[imoc objectWithID:groupObjectID];
[project addGroupsAssignedObject:trainingGroup];
[imoc save];
trainingGroupObjectIDs = nil;
projectObjectID = nil;
project = nil;
trainingGroup = nil;
}
-(void)mergeChanges:(NSNotification *)notification {
NSManagedObjectContext *mainContext = [appDelegate managedObjectContext];
[mainContext performSelectorOnMainThread:#selector(mergeChangesFromContextDidSaveNotification:)
withObject:notification
waitUntilDone:YES];
}
-(void)finalize {
appDelegate = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
imoc = nil;
[super finalize];
}
#end
#implementation NSManagedObjectContext (JGUtilities)
-(BOOL)save {
// If there's an save error, I throw an exception
}
#end
Data Model
Update 1
I've experimented some more, and even without the merge, the exception is still thrown. Just saving the managed object context in another thread after modifying a relationship is enough.
I have a shared persistent store coordinator with the app delegate. I've tried making a separate NSPersistentStoreCoordinator for the thread with the same URL as my data store, but Core Data complains.
I'd love to suggestions on how I can make a coordinator for the thread. The core data docs allude to there being a way of doing it, but I can't see how.
You are crossing the streams (threads in this case) which is very bad in CoreData. Look at it this way:
startTest called from a button (is IBAction, assuming button tap) on Main thread
Your for loop creates a JGMakeRelationship object using the initializer trainGroup: withProject: (this should be called init, and probably call super, but that's not causing this issue).
You create a new managed object context in the operation, on the Main thread.
Now the operation queue calls the operations "main" method from a worker thread (put a breakpoint here and you'll see it's not on the main thread).
Your app goes boom because you've accessed a Managed object Context from a different thread than the one you created it on.
Solution:
Initialize the managed object context in the main method of the operation.
I have use the custom splitview in the my application.
custom splitview .h file
#interface CustomUISplitViewController :UISplitViewController {
BOOL keepMasterInPortraitMode;
BOOL keepMasterInPortraitMode1;
}
and .m file is
-(void) viewWillAppear:(BOOL)animated {
keepMasterInPortraitMode1=keepMasterInPortraitMode;
if(keepMasterInPortraitMode1 == NO) {
if (self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft || self.interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
UIViewController* master = [self.viewControllers objectAtIndex:0];
UIViewController* detail = [self.viewControllers objectAtIndex:1];
[self setupPortraitMode:master detail:detail];
}
}
if (self.interfaceOrientation == UIInterfaceOrientationPortrait || self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
UIViewController* master = [self.viewControllers objectAtIndex:0];
UIViewController* detail = [self.viewControllers objectAtIndex:1];
[self setupPortraitMode:master detail:detail];
}
}
}
- (void)setupPortraitMode:(UIViewController*)master detail:(UIViewController*)detail {
//adjust master view
CGRect f = master.view.frame;
f.size.width = 220;
f.size.height = 1024;
f.origin.x = 0;
f.origin.y =0;
[master.view setFrame:f];
//adjust detail view
f = detail.view.frame;
f.size.width = 548;
f.size.height = 1024;
f.origin.x = 221;
f.origin.y = 0;
[detail.view setFrame:f];
}
This works correctly under iOS4.0 but under 4.2 I see only one view when the app runs. What could change between OS versions?
I was having the same issue and I believe this to be an Apple bug (I filed it a month ago with no response from them.) For me, it was specifically the "detail" view that was blank when the app started at orientation UIInterfaceOrientationLandscapeRight (3). It would look like this: http://d.pr/cGcU. This would occur when I restricted one of the two view controllers (say, the RootViewController) to landscape-only:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
With this in place, the following would occur during the detail view's initialization:
2010-11-15 20:17:47.792 MultipleDetailViews[96250:207] firstDetailViewController willAnimateRotationToInterfaceOrientation: 3 (landscape)
2010-11-15 20:17:47.792 MultipleDetailViews[96250:207] self.view.hidden is: 0
2010-11-15 20:17:47.799 MultipleDetailViews[96250:207] rotating...
2010-11-15 20:17:47.848 MultipleDetailViews[96250:207] firstDetailViewController didRotateFromInterfaceOrientation
2010-11-15 20:17:47.849 MultipleDetailViews[96250:207] self.view.hidden is: 1
For some reason the detail view would mysteriously become hidden during rotation to orientation 3. Until Apple fixes this bug (it doesn't occur in 3.2), my workaround is currently to override the following method in the detail view controller, re-displaying the view after rotation has completed:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
self.view.hidden = NO;
}
EDIT: If your detail view isn't a direct subview of splitViewController.view (e.g. you are using a UINavigationController), you will need to set hidden on the topmost view on the detail side within the UISplitViewController:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
// Make sure you set splitViewController via an outlet or get it via your AppDelegate
for (UIView *splitViewChild in splitViewController.view.subviews)
splitViewChild.hidden = NO;
}
I have had the exact same problem with my applications. I had used the same Subclassing technique to have the Master and Detail visible in both Portrait and Landscape modes. Worked great until 4.2 which, unfortunately I didn't test for when the Beta releases were available.
I recommend trying the excellent MGSplitViewController (http://mattgemmell.com/2010/07/31/mgsplitviewcontroller-for-ipad). It is an open-source implementation of the UISplitViewController. It's only drawback is that it isn't quite as easy to use in Interface Builder, but it includes a sample project. Visually it is identical to UISplitViewController, but adds support for several extras such as dragging the split position at runtime.
Just implement it exactly as your UISplitViewController but add the following line somewhere:
[splitViewController setShowsMasterInPortrait:YES];
This is very similar to the Private API that Apple prohibits using with their version.
//[splitViewController setHidesMasterViewInPortrait:NO]; // Naughty, Naughty, Not allowed by the Apple police