Writing to NSOutputStream cause high cpu usage - ios

While instrumenting my app I found that CPU usage jumps to 90% when writing data to output stream. Specifically, when network speed is very high. When I profile it With Timer instrument, found that most of the cpu is used for NSStream delegate call. Please Help to optimize writing technic as to low down the cpu usage.
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
case NSStreamEventOpenCompleted: {
_isConnected = YES;
if([self.delegate respondsToSelector:#selector(isFTPConnectionFoundForUpload:)])
[self.delegate performSelector:#selector(isFTPConnectionFoundForUpload:) withObject:_isConnected?#"YES":#"NO"];
} break;
case NSStreamEventHasSpaceAvailable: {
bytesWritten = [self.producerStream write:&self.buffer[0] maxLength:512];
if (bytesWritten == -1) {
[self stopSendWithStatus:#"Network write error"];
}
} break;
case NSStreamEventErrorOccurred: {
NSLog(#"producer stream error %#", [aStream streamError]);
[self stopSendWithStatus:#"Stream open error"];
} break;
case NSStreamEventEndEncountered: {
} break;
default: {
} break;
}
}

Related

How to send large file as chunks via MCSession NSOutputStream

I want to send large video file to connected peer in chunks via NSOutputStream
I am using below code.
NSError *error;
self.outputStream = [_appDelegate.mcManager.session startStreamWithName:#"Mystream" toPeer:[[_appDelegate.mcManager.session connectedPeers] objectAtIndex:0] error:&error];
At receiver side NSStream delegate not receiving entire send data.
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
switch(eventCode) {
case NSStreamEventEndEncountered:
break;
case NSStreamEventHasBytesAvailable:
if ([aStream isKindOfClass:[NSInputStream class]]) {
}
break;
case NSStreamEventErrorOccurred:
break;
case NSStreamEventHasSpaceAvailable:
break;
case NSStreamEventNone:
break;
case NSStreamEventOpenCompleted:
break;
}
}

AFNetworkReachabilityManager return NO all the time

[[AFNetworkReachabilityManager sharedManager] startMonitoring];
AFNetworkReachabilityManager*manger =[AFNetworkReachabilityManager sharedManager];
BOOL is=[manger isReachable];
Why does it return NO all the time? I do know I connect the internet with wifi.
Requires some time to Determine network status.
So,isReachable right after startMonitoring will always return false.
You need check isReachable inside setReachabilityStatusChangeBlock ;
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status){
NSLog(#"network staus changed");
//check for network related flag
}];
[[AFNetworkReachabilityManager sharedManager] startMonitoring] will take little bit time to return proper value.
I'm using this code and this works for me!
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(#"Rechability : %#", AFStringFromNetworkReachabilityStatus(status));
switch (status) {
case AFNetworkReachabilityStatusNotReachable:
{
// NO Internet Connection.
break;
}
case AFNetworkReachabilityStatusReachableViaWWAN:
{
break;
}
case AFNetworkReachabilityStatusReachableViaWiFi:
{
break;
}
case AFNetworkReachabilityStatusUnknown:
{
break;
}
default: break;
}
}];
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
Do following steps, this is working code in my project.
Step 1:
//AppDelegate.m
[self startMonitoringTheNetwork];// Call this method didFinishLaunchingWithOptions
Step 2:
#pragma mark - Interenet Connection Status
-(void)startMonitoringTheNetwork {
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusUnknown:
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
//available
break;
case AFNetworkReachabilityStatusNotReachable:
//not available
break;
default:
break;
}
}];
//start monitoring
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
}
Step 3:
Add following class level method to CommonClass.h
+ (BOOL) isInternetConnected;
Step 4:
And implement above method to CommonClass.m
+(BOOL) isInternetConnected {
BOOL isConnected = NO;
if (!isConnected) {
isConnected = [AFNetworkReachabilityManager sharedManager].reachable;
}
return isConnected;
}
Step 5:
Now you are ready to access to the internet status everywhere by importing that CommonClass.h i.e #import "CommonClass.h"
Bool isInternetConnected = [CommonClass isInternetConnected];
Note : Step 3 & 4 are not compulsory, you can directly access if you want.
In the latest Version of AFNetworking,
Reachability should be monitered when the app is launched,ie
you should write the below code in the AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
method, so that the Rechability manager starts monitering the status when the application starts.
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(#"Rechability : %#", AFStringFromNetworkReachabilityStatus(status));
switch (status) {
case AFNetworkReachabilityStatusNotReachable:
{
// NO Internet Connection.
break;
}
case AFNetworkReachabilityStatusReachableViaWWAN:
{
break;
}
case AFNetworkReachabilityStatusReachableViaWiFi:
{
break;
}
case AFNetworkReachabilityStatusUnknown:
{
break;
}
default: break;
}
}];
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
If you want to know the status before performing some operation you can use:
[[AFNetworkReachabilityManager sharedManager] isReachable];
If you want to know immediately if network is cut off, then you can post a NSNotification so that you can receive it anywhere and perform some operation

AFNetworking checking the network available

i'm using the AFN to check the network.
__block BOOL connect;
AFNetworkReachabilityManager*manager = [AFNetworkReachabilityManager sharedManager];
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case -1:
connect=YES;
break;
case 0:
connect=NO;
break;
case 1:
connect=YES;
break;
case 2:
connect=YES;
break;
default:
break;
}
}];
[manager startMonitoring];
and i want to get the Bool connect at another file
if (![ValueUtils isConnectNet])
but it didn't get the bool immediately how can i get the bool first and then do the “if else” thing?
now i use Reachability ,if u use AFN's isReachable right after startMonitoring,it can't get the current network status immediately.
You can check the reachability by this:
AFNetworkReachabilityManager *reachability = [AFNetworkReachabilityManager sharedManager];
[reachability setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN:
NSLog(#"WWN");
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(#"WiFi");
break;
case AFNetworkReachabilityStatusUnknown:
NSLog(#"Unknown");
break;
case AFNetworkReachabilityStatusNotReachable:
NSLog(#"Not Reachable");
break;
default:
break;
}
}];
or you can use:
+(BOOL)IsInternet
{
Reachability *networkReachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];
if (networkStatus == NotReachable)
{
return NO;
}
else
{
return YES;
}
}
You just need to check like this :
if ([[AFNetworkReachabilityManager sharedManager] isReachable])
{
NSLog(#"IS REACHABILE");
}
else
{
NSLog(#"NOT REACHABLE");
}
No need to take bool for this. AFNetworkReachabilityManager give response that network is reachable or not.

NSStream delegate method stream:handleEvent: crashing application with EXC_BAD_ACCESS code=1

I am using NSInputStream to upload media file to server in following way.
uploadInputStream = [[NSInputStream alloc] initWithFileAtPath:videoFilePath];
uploadInputStream.delegate = self;
[uploadInputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[uploadInputStream open];
And in NSStream delegate method stream:handleEvent: i am fetching chunk of media file and uploading to server.
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
switch (eventCode) {
case NSStreamEventOpenCompleted:
NSLog(#"Strem opened");
break;
case NSStreamEventHasBytesAvailable: {
uint8_t buf[1024*1024];
unsigned int len = 0;
len = [(NSInputStream *)aStream read:buf maxLength:1024*1024];
if(len)
{
#autoreleasepool {
NSMutableData *fileData = [NSMutableData data];
[fileData appendBytes:(const void *)buf length:len];
[self uploadVideo:fileData];
}
}
break;
}
case NSStreamEventHasSpaceAvailable:
break;
case NSStreamEventEndEncountered: {
break;
}
case NSStreamEventErrorOccurred:
break;
case NSStreamEventNone:
break;
default:
break;
}
}
So far so good and everything works fine in simulator. The issue is if i test this same code in real device (iPad-mini for now), it always crashing the application with EXC_BAD_ACCESS code=1 at strating of the delegate method stream:handleEvent: .
Anyone has any idea about this? Any help will be appreciated.
Thanks,
Jay Stepin.

AVAssetExportSession SLOW

I am using AVAssetExportSession to export audio files. It is working, though in a speed that is practical for use. I am setting up my exporter, getting my AVAsset, and starting the export. Here is the code. Any suggestions or insight will help.
[exporter exportAsynchronouslyWithCompletionHandler:^{
NSLog(#"we are now exporting");
int exportStatus = exporter.status;
switch (exportStatus) {
case AVAssetExportSessionStatusFailed: {
// log error to text view
NSError *exportError = exporter.error;
NSLog (#"AVAssetExportSessionStatusFailed: %#", exportError);
break;
}
case AVAssetExportSessionStatusCompleted: {
NSLog (#"AVAssetExportSessionStatusCompleted");
// set up AVPlayer
NSData *data = [NSData dataWithContentsOfURL:exportURL];
break;
}
case AVAssetExportSessionStatusUnknown: { NSLog (#"AVAssetExportSessionStatusUnknown"); break;}
case AVAssetExportSessionStatusExporting: { NSLog (#"AVAssetExportSessionStatusExporting"); break;}
case AVAssetExportSessionStatusCancelled: { NSLog (#"AVAssetExportSessionStatusCancelled"); break;}
case AVAssetExportSessionStatusWaiting: { NSLog (#"AVAssetExportSessionStatusWaiting"); break;}
default: { NSLog (#"didn't get export status"); break;}
}
[exporter release];
[exportURL release];
}];
You're probably causing some kind of conversion - that will be slow (not that much faster than realtime). Make sure you're using the passthrough preset, AVAssetExportPresetPassthrough.

Resources