UI Hang in offline mode - ios

Does any body know what I need to check if app freezes after some time ? I mean, I can see the app in the iPhone screen but no view responds.
I did some google and i found that, i've blocked the main thread somehow.
But my question is how to identify which method causes blocking of main thread ? is there any way to identify ?
I using XMPP for chat and core data for storing and retrieving the messages.I connect the app with XMPP Server in app delegate class.But i don't know how XMPP Delegate call again and again. According to me core data doing its work fine but in the offline mode XMPP try to disconnect and until it does not complete its task it freeze the app for some time and then works fine in the offline mode.
But I am not sure what is the culprit.I am not able to find the issue.
And i tried the pause button too when it freeze but in the left window i am not able to find which method make the app freeze.
Here is code which i am using
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"IMChatMessageCell";
CMMessageArchiving_Message_CoreDataObject *msgInfo = (CMMessageArchiving_Message_CoreDataObject *)[[self messageFetchResultController] objectAtIndexPath:indexPath];
IMPromos *promo = nil;
if (msgInfo.promo_Object)
{
promo = msgInfo.promo_Object;
////NSLog(#"%#", promo);
}
else
{
promo = [IMDataHandler fetchPromoForPromoID:msgInfo.promo_id];
msgInfo.promo_Object = promo;
}
if (msgInfo.mediaThumbnailPath)
return [self mediaMessageCell:tableView indexPath:indexPath messageInfo: msgInfo];
IMChatMessageCell chatMessageCell = (IMChatMessageCell)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (chatMessageCell == nil)
{
NSArray *objects = [[NSBundle mainBundle] loadNibNamed:cellIdentifier owner:nil options:nil];
for (NSObject *obj in objects)
{
if ([obj isKindOfClass:[IMChatMessageCell class]])
{
chatMessageCell = (IMChatMessageCell *)obj;
break;
}
}
}
int imageWith;
NSString *message = [msgInfo body];
if (NO == msgInfo.isOutgoing)// left aligned
{
// Just set the textfield here ///
NSString* promoImage = [[IMUtils getImageFolderPath] stringByAppendingPathComponent: [chatMessageCell.cellPromo.promo_image lastPathComponent]];
//NSLog(#"%#",promoImage);
UIImage *image = [UIImage imageWithContentsOfFile:promoImage];
if (image)
{
chatMessageCell.userImageView.image = image;
if(!promo.promo_message.length)
{
chatMessageCell.userImageView.frame = CGRectIntegral(CGRectMake(padding, 15, image.size.width,image.size.height));
bubbleItemOrigin=USER_IMAGE_Y_POS_WITHOUT_HEADER;
if(!promo.promo_link.length)
bubbleItemOrigin-=5;
}
else
{
chatMessageCell.userImageView.frame = CGRectIntegral(CGRectMake(padding, USER_IMAGE_Y_POS, image.size.width, image.size.height));
bubbleItemOrigin=USER_IMAGE_Y_POS;
}
}
return chatMessageCell;
}
(void)viewWillAppear:(BOOL)animated
{
[self scrollToBottom];
[super viewWillAppear:animated];
[self refreshTitleView];
messagesFetchResultController.delegate = self;
messageTextField.font = [IMUtils appFontWithSize:font_size];
}
I am using this code.
When i am running the app without network then it freeze
and something like this printing into logs
and XMPP'S delegate get called.

Related

Correct way to store logs for iOS

I have an in-home app that will be supported by IT team.
When they support desktop apps, they may read logs to find any troubles (like server returned 404 on sync request).
I can use NSLog for iOS, but how can user access them with out of Xcode?
I can't ask any user "please give me your phone to investigate what has happened".
Does there is some tool any IT person with out of Xcode and Mac may use to read iOS logs?
Does there is some tool any IT person with out of Xcode and Mac may use to read iOS logs?
Unfortunately not. It used to be that you could run an app on your device that would read the Console log, but Apple took that ability away; I guess they saw it as a security breach.
If your user can get to a Mac running Xcode, they can view the console log directly in Xcode.
Otherwise, as others have suggested, you will have to build into your app the capacity to keep a log in a place you can get to. For example you can write to a file and then offer (within the app) to email that file to yourself. Many apps have an interface to a facility like this in their Settings bundle.
I've been using the combination of CocoaLumberjack, Antenna & DDAntennalogger at work for remote logging. Basically, you have to set up an end-point at your server and Antenna will be used to send the logs remotely.
Here's the reference that when configuring it on my project:
Remote logging using CocoaLumberjack, Antenna & DDAntennaLogger
This is how you can do it:
Step 1: Redirect your NSLog statements to a text file in file system. This you can do on specific user action or always enable it and delete it periodically.
Step 2: Have a web service which will allow you to upload the saved logs in the file system. You could trigger this on user action or may be a timer based job.
Step 3: Delete the logs from file system once upload is successful.
Here is a example of such a custom logger:
#import "MyCustomLogging.h"
#define kMyCustomLoggingFile #"NSLogging.txt"
static NSString *const kMyDeviceLogUploadURL = #"uploadDeviceLogURL";
#interface MyCustomLogging ()
#property (nonatomic, strong) MyRequestHandler *requestHandler;
#property (nonatomic, assign, getter = isNsLogRedirected) BOOL nsLogRedirected;
#property (nonatomic, assign) BOOL shouldStopLogging;
#property (nonatomic, strong) NSString *pathForLogging;
#end
#implementation MyCustomLogging
static int savedStdErr = 0;
static MyCustomLogging *sharedMyCustomLogging = nil;
+ (MyCustomLogging *)sharedMyCustomLogging {
static dispatch_once_t pred = 0;
dispatch_once(&pred, ^{
sharedMyCustomLogging = [[self alloc] init];
});
return sharedMyCustomLogging;
}
#pragma mark -
#pragma mark Start Method
- (void)startLogging {
// Starting the Redirection of the Logs
if (!self.isNsLogRedirected) {
[self nsLogRedirectedToFile];
}
}
#pragma mark -
#pragma mark Stop Method
- (void)stopLogging {
NSLog(#"Stopping the logging");
NSString *aLoggingPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
self.pathForLogging = [aLoggingPath stringByAppendingPathComponent:kMyCustomLoggingFile];
// If file already exists & logging was not redirected then directly upload the logs::A Possible case of app quit/crash without uploading previous logs
if ([self isLogFilePresent] && !self.nsLogRedirected) {
[self uploadLogs];
} else if (self.isNsLogRedirected) { //Check for Successive Stop Notifications
self.shouldStopLogging = YES;
[self restoreNSLog];
} else {
NSDictionary *anUserInfo = #{kMyDeviceLogUplodStatusKey: kMyValueOne};
[[NSNotificationCenter defaultCenter] postNotificationName:kMyDeviceLogsUploadNotification object:nil userInfo:anUserInfo];
}
}
#pragma mark -
#pragma mark Private Method
- (void)nsLogRedirectedToFile {
if (!self.isNsLogRedirected) {
NSLog(#"Redirecting NSLogs to a file.....");
self.nsLogRedirected = YES;
savedStdErr = dup(STDERR_FILENO);
NSString *aLoggingPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
self.pathForLogging = [aLoggingPath stringByAppendingPathComponent:kMyCustomLoggingFile];
NSLog(#"Logging Path: %#", self.pathForLogging);
freopen([self.pathForLogging cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
NSLog(#"NSLog Redirected to a file Succesfully");
[MySessionObject setLoggingOn:YES];
}
}
- (void)restoreNSLog {
if (self.isNsLogRedirected) {
[MySessionObject setLoggingOn:NO];
NSLog(#"NSLog Will be Restored now....");
self.nsLogRedirected = NO;
fflush(stderr);
dup2(savedStdErr, STDERR_FILENO);
close(savedStdErr);
savedStdErr = 0;
}
[self uploadLogs];
NSLog(#"NSLog Restored Successfully");
}
- (void)uploadLogs {
NSLog(#"Now uploading files");
// Disable logging before files are uploading
MySessionObject.enableLogging = NO;
NSError *anError = nil;
NSData *aLogData = [NSData dataWithContentsOfFile:self.pathForLogging options:NSDataReadingUncached error:&anError];
//Converting to String
NSString *aLogString = [[NSString alloc] initWithData:aLogData encoding:NSUTF8StringEncoding];
NSMutableDictionary *aPostBody = [[NSMutableDictionary alloc] initWithCapacity:3];
[aPostBody setValue:aLogString forKey:#"logData"];
[aPostBody setValue:MySessionObject.wifiMACAddress forKey:#"deviceMACAddress"];
[aPostBody setValue:MySessionObject.deviceToken forKey:#"deviceID"];
__weak MyCustomLogging *aBlockSelf = self;
self.requestHandler = [[MyRequestHandler alloc] initWithEndPoint:#"/uploadLogs" body:aPostBody container:nil loadingOverlayTitle:nil successHandler:^(NSDictionary *iResponse) {
if (iResponse) {
//Remove the File From the Path
NSError *aFileError = nil;
BOOL aFileRemoveSuccess = [[NSFileManager defaultManager] removeItemAtPath:self.pathForLogging error:&aFileError];
if (!aFileRemoveSuccess) {
//Tracking the Event
NSString *aDescription = [NSString stringWithFormat:#"Error Code:%ld Error Description:%#", (long)[aFileError code], [aFileError localizedDescription]];
NSLog(#"Error occured while deleting log file:%#", aDescription);
}
// Clearing all
aBlockSelf.pathForLogging = nil;
NSDictionary *anUserInfo = #{kMyDeviceLogUplodStatusKey: kMyValueOne};
[[NSNotificationCenter defaultCenter] postNotificationName:kMyDeviceLogsUploadNotification object:nil userInfo:anUserInfo];
}
} andErrorHandler:^(NSString *iMessage, NSString *iKey, NSInteger iErrorCode, BOOL iIsNetworkError) {
NSDictionary *anUserInfo = #{kMyDeviceLogUplodStatusKey: kMyValueZero};
[[NSNotificationCenter defaultCenter] postNotificationName:kMyDeviceLogsUploadNotification object:nil userInfo:anUserInfo];
}];
[self.requestHandler executeRequest];
}
- (BOOL)isLogFilePresent {
NSFileManager *aFileManager = [[NSFileManager alloc] init];
BOOL aFilePresent = [aFileManager fileExistsAtPath:self.pathForLogging];
return aFilePresent;
}
#end

iOS - accessing array returned by API gives EXC_BAD_ACCESS (code=1)

I am trying to make a Facebook/9gag like comment page in an iOS app. Briefly speaking, there will be a list of images in a list view, and there is a comment button, wheneven users press it, a comment list view will be shown just like those in Facebook and 9gag.
In my project, I created several classes to achieve this, which are:
APIOperator, which defines the path of the api to call, and called whenever a request is made to the server
MyPhotoCell, which is a custom UITableViewCell class forming the photo list view, consisting an image and a comment button
CommentViewController, which is the controller for the comment list displayed
CommentCell, which is a custom UITableViewCell forming the comment list displayed
And below are the code segments regarding the issue:
Firstly, when the user presses the comment button in one of the MyPhotoCell, it will invoke the creation of CommentListViewController:
//MyPhotoCell.m
- (void)click_btn_comment:(id)sender
{
CommentViewController *comment_view = [[CommentViewController alloc] initWithNibName:#"CommentViewController" bundle:nil];
comment_view.targetPhotoid = self.photoItem.photoid;
[[MyAppCoreData coreData].navController pushViewController:comment_view animated:YES];
}
Following with:
//CommentViewController.h
#property (assign, nonatomic) NSInteger targetPhotoid;
#property (strong, nonatomic) NSMutableArray *arr_commentList;
//CommentViewController.m
#interface SecondCreation_CommentViewController ()<UITableViewDataSource, UITableViewDelegate>
{
ASIHTTPRequest *request_comment;
}
#property (strong, nonatomic) UITableView *tbl_comment;
#property (strong, nonatomic) NSNumber *page;
#end
- (void)viewWillAppear:(BOOL)animated
{
if(!self.tbl_comment){
self.tbl_comment = [[UITableView alloc] init];
self.tbl_comment.delegate = self;
self.tbl_comment.dataSource = self;
self.tbl_comment.frame = CGRectMake(0, 55, PHOTOWIDTH, SCREEN_HEIGHT - 100);
[self.view addSubview:self.tbl_comment];
}
if([NSArray checkEmptyArray:self.arr_commentList]){
self.page = 0;
[self sendRequest:1];
}
}
- (void)addDisplayData:(NSArray *)arr_addData withReset:(BOOL)reset
{
//NSLog here shows arr_addData has a count of 6 (6 comments inside, which is normal)
//NSLog here shows arr_commentList has a count of 0 (which is also expected)
if (reset) {
[self.arr_commentList removeAllObjects];
}else {
if (!self.arr_commentList) {
self.arr_commentList = [NSMutableArray array];
}
}
[self.arr_commentList addObjectsFromArray:arr_addData];
//NSLog here shows arr_addData still has a count of 6
//NSLog here shows arr_commentList has a count of 6
}
- (void)sendRequest:(NSInteger)page
{
__block typeof(self)blockSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
blockSelf -> request_comment = [APIOperator getCommentListForPhoto:#(self.targetPhotoid) andPage:page WithCompletionHandler:^(APISTATUS apiStatus, CommentListItem *commentListItem, ASIHTTPRequest *request) {
if (request != blockSelf -> request_comment) {
return;
}
dispatch_async(dispatch_get_main_queue(), ^(void) {
if (apiStatus == APISTATUS_SUCCESS) {
//I tried to access and print out the content of the returned commentList here, and it gives EXC_BAD_ACCESS (code = 1 ......)
//e.g. NSLog(((CommentItem *)[commentListItem.commentList objectAtIndex:0]).message);
//I tried to assign the returned commentList to my controller through various ways like:
//[blockSelf.arr_commentList addObjectsFromArray:commentListItem.commentList];
//[blockSelf.arrcommentList = commentListItem.commentList;
//[blockSelf addDisplayData:commentListItem.commentList withReset:YES];
//I tried to access the content of controller's arr_commentList, it will give EXC_BAD_ACCESS (code = 1, .....) too
} else {
}
});
}];
});
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"commentcell";
CommentCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if(!cell)
cell = [[CommentCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
//acessing the local arr_commentList here will also gives EXC_BAD_ACCESS (code = 1.....)
return cell;
}
And finally, the APIOperator class where the api request is made(ASIHTTPREQUEST is a wrapper class that used to send HTTP request to server and interacts with RESTFUL api, link: link here):
//APIOperator.m
+ (ASIHTTPRequest *)getCommentListForPhoto:(NSNumber *)photoid andPage:(NSInteger)page WithCompletionHandler:(void(^)(APISTATUS apiStatus, CommentListItem *apiItem, ASIHTTPRequest *request))completionBlock
{
NSString *str_page = [NSString stringWithFormat:#"%#", #(page)];
//API_URL here is the url to call the api in the server
NSString *str_API = [NSString stringWithFormat:#"%#",API_URL];
ASIHTTPRequest *_request = [ASIHTTPRequest createAPIRequest:str_API];
__block ASIHTTPRequest *request = _request;
__block void(^tempBlock)(APISTATUS apiStatus, CommentListItem *apiItem, ASIHTTPRequest *request) = completionBlock;
[_request setCompletionBlock:^{
if ([request responseStatusCode] == 200 || [request responseStatusCode] == 302 || [request responseStatusCode] == 304) {
DEBUGMSG(#"%d %#",[request responseStatusCode], request.url)
JSONParse *jsonParse = [[JSONParse alloc] initWithData:[request responseData]];
CommentListItem *obj = (CommentListItem *)[jsonParse parser2OneObject:#"CommentListItem" withPath:nil];
//I tried to print out the contents of the comments here, and everything are as expected
NSLog(((CommentItem *)[obj.commentList objectAtIndex:0]).message);
jsonParse = nil;
if (tempBlock) {
tempBlock(APISTATUS_SUCCESS,obj,request);
}
tempBlock = nil;
request = nil;
} else {
DEBUGMSG(#"%d %#",[request responseStatusCode], request.url)
if (tempBlock) {
tempBlock(apiStatus,nil,request);
}
tempBlock = nil;
request = nil;
}
}];
[_request setFailedBlock:^{
DEBUGMSG(#"%d %#",[request responseStatusCode], request.url)
if (tempBlock) {
tempBlock(apiStatus,nil,request);
}
tempBlock = nil;
request = nil;
}];
[_request performSelector:#selector(startAsynchronous)];
return _request;
}
I searched on the internet and found out that EXC_BAD_ACCESS code = 1 is about accessing/releasing a variable that is already released/deallocated before, but I still can't figure out the problem here. I can't find where it is released/deallocated, and why it still give me a count of 6 if it is released/deallocated. Hope I can get some help here about what is causing this problem and how to deal with it, as I've already dealing with this problem for a long time, but still have no idea about what the problem is and what to do. Thanks a lot!

'NSInternalInconsistencyException', reason: 'Only run on the main thread!' error

So I know the reason for this error, but I'm not really sure how to get around it.
I have a TextField that I want to not be editable, but with scrolling enabled inside a view.
This is how I set up that view:
- (void)tableView:(UITableView *) tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *component = self.resultsTuples[indexPath.row];
NSString* serverUrl = #"http://staging.toovia.com";
NSString* pageLink = component[#"$element"][#"ContactCard"][#"PageLink"];
NSString* recUrl =[NSString stringWithFormat:#"%#%#&format=json&fields=summary&fields=session_info", serverUrl,pageLink];
[AJAXUtils getAsyncJsonWithUrl:(NSURL *)[NSURL URLWithString:recUrl] callback:^(NSDictionary *returnjson){
if (returnjson != nil){
NSLog(#"RETURN JSON : %#", returnjson);
NSString *userPageLink = returnjson[#"Node"][#"SessionInfo"][#"PostingAs"][#"Key"];
self.detailController.userPageLink = userPageLink;
self.detailController.nodePage = returnjson[#"Node"][#"Key"];
NSString *selectedCard = component[#"$element"][#"Title"];
// [self.detailController setDescription:component[#"element"][#"ContactCard"][#"Description"]];
[self.detailController setPageTitle:selectedCard];
NSString* photoUrl = component[#"$element"][#"ContactCard"][#"Cover"][#"Medium"][#"Link"];
[self.detailController setRestaurantImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:photoUrl]]]];
self.detailController.title = selectedCard;
NSString* rating = component[#"$element"][#"Summary"][#"AverageRating"];
self.detailController.rating =(NSInteger)rating;
[self.navigationController pushViewController:self.detailController animated:YES];
}
}];
This is the viewWillAppear code for the view:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear: animated];
self.rateView.notSelectedStar =[UIImage imageNamed:#"star-off.png"];
self.rateView.fullSelectedStar = [UIImage imageNamed:#"star-on.png"];
self.rateView.rating = self.rating;
self.rateView.editable = YES;
self.rateView.maxRating = 5;
self.rateView.delegate = self;
_pageTitleLabel.text = _pageTitle;
_pageScoreLabel.text = _pageScore;
_trendingImageView.image = [UIImage imageNamed:#"trending.png"];
_restaurantImageView.image = _restaurantImage;
}
The full error is -
2013-12-16 01:22:50.362 ReviewApp[7332:441f] *** Assertion failure in void _UIPerformResizeOfTextViewForTextContainer(NSLayoutManager *, UIView<NSTextContainerView> *, NSTextContainer *, NSUInteger)(), /SourceCache/UIFoundation_Sim/UIFoundation-258.1/UIFoundation/TextSystem/NSLayoutManager_Private.m:1510
2013-12-16 01:22:50.365 ReviewApp[7332:441f] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!'
So I guess it's happening because the resizing of the text field (when content is set) has to happen on the main thread. How do I force this to happen/suppress this error? I'm not in control of the text field resizing am I?
Thanks
I'm guessing that the callback from AJAXUtils happens on a background thread. I don't know if that is your code or not but you should do all UI operations (like setting text in a label, setting an image in an image view, pushing a view controller) on the main thread.
dispatch_sync(dispatch_get_main_queue(), ^{
/* Do UI work here */
});
Swift 3.0 version
DispatchQueue.main.async(execute: {
/* Do UI work here */
})
You must always perform UI code on the main thread. You are not, hence the error. Try this:
[AJAXUtils getAsyncJsonWithUrl:(NSURL *)[NSURL URLWithString:recUrl] callback:^(NSDictionary *returnjson){
if (returnjson != nil){
NSLog(#"RETURN JSON : %#", returnjson);
NSString *userPageLink = returnjson[#"Node"][#"SessionInfo"][#"PostingAs"][#"Key"];
self.detailController.userPageLink = userPageLink;
self.detailController.nodePage = returnjson[#"Node"][#"Key"];
NSString *selectedCard = component[#"$element"][#"Title"];
// [self.detailController setDescription:component[#"element"][#"ContactCard"][#"Description"]];
[self.detailController setPageTitle:selectedCard];
NSString* photoUrl = component[#"$element"][#"ContactCard"][#"Cover"][#"Medium"][#"Link"];
[self.detailController setRestaurantImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:photoUrl]]]];
self.detailController.title = selectedCard;
NSString* rating = component[#"$element"][#"Summary"][#"AverageRating"];
self.detailController.rating =(NSInteger)rating;
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController pushViewController:self.detailController animated:YES];
});
}
}];
This ensures the display of the view controller is on the main thread. You may actually need to put a bit more of the code inside the call to dispatch_async.
Swift version
dispatch_async(dispatch_get_main_queue()){
/* Do UI work here */
}
Also, it's not a very good way of doing things in didSelectRow. You should have a network layer, separate the network code from view controllers otherwise you will end up with huge view controller, code won't be testable.

Cocos2D MenuLevel how to lock, unlock

I am using MenuLevel in my game for loading levels.. http://www.prioregroup.com/iphone/menulevel.aspx
At the moment, whether a level is locked or not, it's loading.. If it's locked, it should not be loading.. How can I do that? Thanks..
// create menu item
[menu createMenuItemLevel:1 position:ccp(x, size.height / 2) life:0 locked:NO];
- (void)menuLevel:(MenuLevel *)menuLevel buttonSelected:(id)source
{
CCMenuItem *item = (CCMenuItem*)source;
NSString *msg = [NSString stringWithFormat:#"You have pressed the button # %d", item.tag]; // retrieve level number..
NSLog(#"MenuLevel Sample %#", msg);
// What I want is something like.. if (item.locked == YES) do something
}
You can use the userData property. In your MenuLevel.m file add the following lines in
- (CCMenuItem*)createMenuItemLevel:(NSInteger)level
position:(CGPoint)position
life:(NSInteger)life
locked:(BOOL)locked
target:(id)target
selector:(SEL)selector
method.
if (locked)
{
item.userData = #"locked";
}
else
{
item.userData = #"notLocked";
}
And in your buttonSelected: method check that userData as given below:
NSString *lockString = (NSString *)item.userData;
if ([lockString isEqualToString:#"locked"])
{
// Locked level
}
else
{
// Unlocked
}

FTP,Blackraccoon Memory leaks

I am working with Blackraccoon FTP client to do FTP operations,working with ARC.but i am getting leaks in instruments.
but there were no leaks in sample application here is my code
BRRequestCreateDirectory *createEventDir = [BRRequestCreateDirectory initWithDelegate:nil];
//NSString *EventCode = [[NSUserDefaults standardUserDefaults] stringForKey:kEventCodeKey];
createEventDir.path = #"/12341234";
createEventDir.hostname = #"media.example.com/httpdocs/events/";
createEventDir.username = #"badboy";
createEventDir.password = #"hai!";
createEventDir.tag = 103;
[createEventDir start];
createEventDir = nil;
sample code from FTP clent Blackraccoon FTP client
leaks showing in instruments like,but i am using ARC
can any one help me to solve this prob..
I ported and heavily modified BlackRaccoon. It is designed to use delegates. In other words, delegates are required.
BRRequestCreateDirectory *createEventDir = [BRRequestCreateDirectory initWithDelegate:nil];
//NSString *EventCode = [[NSUserDefaults standardUserDefaults] stringForKey:kEventCodeKey];
createEventDir.path = #"/12341234";
createEventDir.hostname = #"media.example.com/httpdocs/events/";
createEventDir.username = #"badboy";
createEventDir.password = #"hai!";
createEventDir.tag = 103;
[createEventDir start];
createEventDir = nil;
Is incorrect. It starts a lot of things going and then deletes the object - the action is undefined.
Instead you need something as indicated in the code that I provided (that doesn't leak).
First, the class that uses the ftp needs to have BRRequestDelegate to indicate the delegate protocol.
- (IBAction) createDirectory:(id)sender
{
//----- createEventDir must be a variable in your class...
createEventDir = [BRRequestCreateDirectory initWithDelegate: self];
createEventDir.path = #"/12341234;
createEventDir.hostname = #"media.example.com/httpdocs/events/";
createEventDir.username = #"badboy";
createEventDir.password = #"hai!";
[createEventDir start];
//----- createEventDir MUST NOT BE DELETED OR SET TO NIL HERE
}
Then you have to have the two delegates (at a minimum):
-(void) requestCompleted: (BRRequest *) request
{
//----- handle Create Directory
if (request == createEventDir)
{
NSLog(#"%# completed!", request);
//----- everything is done, NOW you can set it to nil
createEventDir = nil;
}
}
-(void) requestFailed: (BRRequest *) request
{
if (request == createEventDir)
{
NSLog(#"%#", request.error.message);
//----- everything is done, NOW you can set it to nil
createEventDir = nil;
}
}
If you go back and look at my test code you'll see how things work. If you are still having issues, post in the issues on http://github.com/lloydsargent/BlackRaccoon
Hopefully this will get you past your problem.

Resources