I am using a package called BlackRaccoon to upload files to an FTP server. I'm really struggling with a really basic delegation concept that I just cant figure out.
In my uploading class .m file, I have a method which calls the BlackRaccoon uploading request. I use the following code:
uploadFile = [BRRequestUpload initWithDelegate: self];
uploadFile.path = #"/filehere.txt";
uploadFile.hostname = #"xxx";
uploadFile.username = #"xxx";
uploadFile.password = #"xxx";
//we start the request
[uploadFile start];
And in my .h file i have the following:
#interface myClass : NSObject <BRRequestDelegate>
{
BRRequestCreateDirectory *createDir;
BRRequestDelete * deleteDir;
BRRequestListDirectory *listDir;
BRRequestUpload *uploadFile;
NSData *uploadData;
}
Every time I compile and run, I get an error somewhere in the BlackRaccoon files such as:
__25-[BRStreamInfo openRead:]_block_invoke [Line 190] No response from the server. Timeout.
On sourcing this error, I find myself in the method creating the read stream, particularly:
request.didOpenStream = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC), dispatch_get_local_queue(), ^{
if (!request.didOpenStream && request.error == nil)
{
InfoLog(#"No response from the server. Timeout.");
request.error = [[BRRequestError alloc] init];
request.error.errorCode = kBRFTPClientStreamTimedOut;
[request.delegate requestFailed: request];
[request.streamInfo close: request];
}
});
I am totally flunked by this. Our server is up and running and has no timeout issues with our android devices or apps such as 'FTP Sprite'.
Im pretty sure the issue lies with the initWithDelegate stuff. I just dont think im delegating correctly, but Im not sure why. Does anybody have any ideas? I know I am in need of (id)init somewhere, but I just dont understand where or how.
Thanks!
Just checked the uploadFile function at BlackRaccoon Git, and I found that in their example, they don't alloc a BRRequestUpload object, but call it like this :
uploadFile = [BRRequestUpload initWithDelegate: self];
Might this be the cause of your crash?
Please make one line change in BRRequest.m file.
In - (id)initWithDelegate:(id<BRRequestDelegate>)aDelegate Function.
Change
self.passiveMode = YES;
to
self.passiveMode = NO;
And it will work....
That change worked for me.
Related
I created my iMessage extension, when I try to open it, the first screen appears but it is totally frozen, and it does not react in any way.
I've put logs in the viewDidLoad of that first view and nothing appears there, after a few seconds I can already see those logs.
To make the application freezing lose that status, user has to slide screen left or right and back again.
I've tried looking all over the web for someone who happens to be the same, but I could not find anything.
It does not come to mind more screenshots or portions of code add, if you think I should provide some additional information, just let me know
Any help would be appreciated.
Thank you.
UPDATE:
This is my Project Structure.
This is my viewDidLoad code.
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"here viewDidLoad iMessage ext~~~!");
[self applyCornerRadiusToBtn];
[self registerPresentationAction];
NSDictionary *user = [self getUserInfoFromHostApp];
if (user) {
NSLog(#"Here != null user info");
//It is assumed that when you enter this point and run this log, the app should navigate to the next screen, but it does not.
[self performSegueWithIdentifier:#"goToYoutubeListIm" sender:nil];
} else {
NSLog(#"Here userInfo null");
}
}
- (NSDictionary *)getUserInfoFromHostApp
{
NSUserDefaults *myDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.com.xxxxx"];
NSDictionary *userNameSaved = [myDefaults objectForKey:#"userInfoExt"];;
NSLog(#"userNameSaved in xxxx Ext ==> %#",userNameSaved);
NSURL *groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:#"group.com.xxxx"];
NSLog(#"groupURL ==> %#",groupURL);
return userNameSaved;
}
For all concerned I have found the problem or problems to be accurate.
1) I was creating my controllers type MSMessagesAppViewController. Apparently there should only be one controller of this type.
2) I had logic in the viewDidAppear in my MSMessagesAppViewController. For some strange reason this also caused the problem, I had to get the logic out there and force the user to interact with a button to execute the logic that was in the didAppear
Any idea why startAccessingSecurityScopedResource always returns NO in the following callback of UIDocumentPickerViewController:
- (void)documentPicker:(UIDocumentPickerViewController*)in_documentPickerViewController didPickDocumentAtURL:(NSURL*)in_pickedDocumentAtURL
{
BOOL l_bStartAccessingWorked = [in_pickedDocumentAtURL startAccessingSecurityScopedResource];
....
void(^l_coordinateReadingAccessor)(NSURL*) = ^(NSURL* in_coordinateReadingURL)
{
....
};
NSFileCoordinator* l_fileCoordinator = [[[NSFileCoordinator alloc] init] autorelease];
NSError* l_error = nil;
[l_fileCoordinator coordinateReadingItemAtURL:in_pickedDocumentAtURL
options:0
error:&l_error
byAccessor:l_coordinateReadingAccessor];
[in_pickedDocumentAtURL stopAccessingSecurityScopedResource];
}
I tried both my own App and Apple's NewBox example, tried on a few devices, and always get NO. However, the subsequent "coordinateReadingItemAtURL" works just fine.
Very late, but I think NO means either access-denied or, more likely, the URL was not actually security-scoped. So, your call to stopAccessingSecurityScopedResource should be inside an if ( l_bStartAccessingWorked ) block.
I'm still learning this, so I could be mistaken. It fits my experience so far.
I'm trying to breath life back into a project from iOS 7.1 onto iOS 8.1. Obviously this is a NewsStand app. I need to be able to validate a certificate manually against a different host name. This all happens inside of willSendRequestForAuthenticationChallenge. On iOS 7.1 this all works fine. I even retested with an iPad still running 7.1 and it works, but on iOS 8.1 the method is never being invoked. As a result all Asset downloads fail with didFailWithError being invoked and an error of "The operation couldn’t be completed. (NSURLErrorDomain error -1202.)"
Does anyone know What might have changed in iOS 8.1 that would cause this? Are they not making the call? Did anything change with regards to inheritance on iOS 8.1 that might effect whether methods are detected and called? I did try moving all methods into the top class, but that didn't seem to help. Is it possible this is a result of using a "POST" request?
For the life of me I don't see any obvious code reason why willSendRequestForAuthenticationChallenge is not getting called on iOS 8.1 for NKAssetDownload, but is called for iOS 7.1. I never tested with iOS 8.0, so I can't say for sure it wasn't called there.
Note that the method is called for all my other URL connections I am using on iOS 8.1, so the issue seems to be specific to NKAssetDownload (or at least my invocations of NKAssetDownload).
The relevant code is:
#implementation myDownloader
{
NKIssue * theIssue; // pointer to the magazine Issue object
NSString * theJsonReceiptArrayBase64String;
NKAssetDownload * theAssetDownload;
NSString * sourceURL;
NSString * theFileName;
NSString * issueUniqueId;
NSURLConnection * theConnection;
NSNumber * expectedFileSize;
}
...
-(myDownloader *)initWithIssueAndIdAndSourceAndFinalPath:(NKIssue *)issue uniqueId:(NSString *)uniqueId source:(NSString *)source fileName:(NSString *)fileName fileSize:(NSNumber *) fileSize Receipt:(NSString *)receipt
{
NSLog(#"initWithIssueAndIdAndSourceAndFinalPath");
self = [super init];
if (self)
{
theIssue = issue;
sourceURL = source;
theFileName = fileName;
issueUniqueId = uniqueId;
expectedFileSize = fileSize;
theJsonReceiptArrayBase64String = receipt;
}
return self;
}
...
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection
{
/* never get here on iOS 8.1 */
return NO;
}
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
/* never get here on iOS 8.1 */
[self handleAuthenticationOnConnection:connection withChallenge:challenge];
}
...
-(void) downloadPackage
{
CCommunictionMgr * communicator = [CCommunictionMgr instance];
NSMutableURLRequest * thePackageRequest = [communicator generateJsonPostPackageRequest:sourceURL uniqueId:issueUniqueId recieptData:theJsonReceiptArrayBase64String];
theAssetDownload = [theIssue addAssetWithRequest:thePackageRequest];
[theAssetDownload setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:kASSET_TYPE_PACKAGE, kASSET_TYPE_DK, nil]];
theConnection = [theAssetDownload downloadWithDelegate:self];
}
the object "myDownloader" implements both NSURLConnectionDelegate, NSURLConnectionDownloadDelegate
headerfile
#interface myDownloader : CConnectionDelegate <NSURLConnectionDelegate, NSURLConnectionDownloadDelegate>
...
where the guts of the authentication challenge are handled inside the CConnectionDelegate object.
I am happy to include the guts of other code if needed.
According to the OpenGL ES Programming guide's section on texturetool,
Your app must parse the data header to obtain the actual texture data. See the
PVRTextureLoader sample for an example of working with texture data in the PVR format.
This is all well and good, but 3 years later, and PVRTextureLoader's PVRTexture.m doesn't compile because it needs to be converted in order to work in an ARC project. I reckon I could flag these two files as non-ARC but I wanted to at least learn a little about Objective-C this time around.
Here's a bit of code that's giving me trouble at this point:
+ (id)pvrTextureWithContentsOfFile:(NSString *)path
{
return [self initWithContentsOfFile:path];
}
This was manually converted from:
+ (id)pvrTextureWithContentsOfFile:(NSString *)path
{
return [[[self alloc] initWithContentsOfFile:path] autorelease];
}
Maybe someone could be so kind as to walk through what this actually does (as it makes no sense to me to refer to self from what is clearly declared as a class method and not an instance method), but the actual error seen is
<...>/PVRTexture.m:256:15: error: no known class method for selector 'initWithContentsOfFile:'
return [self initWithContentsOfFile:path];
^~~~~~~~~~~~~~~~~~~~~~
1 error generated.
As for why I am manually converting this file to ARC, the Edit->Refactor->Convert to Objective-C ARC... menu option basically says "fix these 8 errors before I can continue" and these 8 errors are of course ARC-related errors. Which I was hoping the conversion would be able to resolve. Circular dependencies are only fun the first time around.
The curious bit is that -initWithContentsOfFile:path is right there in the file too:
- (id)initWithContentsOfFile:(NSString *)path
{
if (self = [super init])
{
NSData *data = [NSData dataWithContentsOfFile:path];
_imageData = [[NSMutableArray alloc] initWithCapacity:10];
_name = 0;
_width = _height = 0;
_internalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
_hasAlpha = FALSE;
if (!data || ![self unpackPVRData:data] || ![self createGLTexture])
{
self = nil;
}
}
return self;
}
Note: This code compiles if I change the + to a - on the pvrTextureWithContentsOfFile declaration. I am positive the original code had a + there, so please, somebody help explain this to me.
alloc is a class method. You usually see alloc used from another class, with things like:
NSView *myView = [[NSView alloc] initWithFrame: someRect];
In a class method, self is the class, not an instance of that class. So [self alloc] allocates an instance of the class. It would also be valid to use the name of the class explicitly, so in the case of your PVRTexture class,
return [[self alloc] initWithContentsOfFile:path];
Could be replaced with
return [[PVRTexture alloc] initWithContentsOfFile:path];
Both are perfectly valid. I would probably use the second form, just because, like you, I find the first form a little odd-looking.
I got it, I think. Here's another example where writing out the question leads to the answer.
It's this:
return [[self alloc] initWithContentsOfFile:path];
I'm sure Google will be happy enough to (let SO) show me what alloc actually does. I guess calling [self alloc] from a class method is essentially what makes that method into a factory method that can generate instances of that class. This is nothing other than the Obj-C way to new something.
Me, I made the mistake of assuming alloc was something that ARC abolished.
Also, a side note: Reading carefully helps. I also just found out about GLKTextureLoader so I didn't need to convert PVRTextureLoader at all.
is it possible to load an external index.html (with included cordova.js) instead of the local one?
i found in the appdelegate.m this code:
self.viewController.wwwFolderName = #"www";
self.viewController.startPage = #"index.html";
i tried to reference an external url but without luck... anyone know a solution for this?
p.s.
with android it's easy:
super.loadUrl("http://192.168.1.135:3000/");
I have done this for my project (AppDelegate.m):
self.viewController = [[[MainViewController alloc] init] autorelease];
self.viewController.useSplashScreen = YES; // YES;
self.viewController.wwwFolderName = #""; // #"www";
self.viewController.startPage = #""; // #"index.html";
self.viewController.invokeString = invokeString;
self.viewController.view.frame = viewBounds;
// Load request with new root URL
NSURL *urlOverwrite = [NSURL URLWithString:#"http://kyryll.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:urlOverwrite];
[self.viewController.webView loadRequest:request];
As mentioned elsewhere, the site you are trying access has to be whitelisted.
It's working nicely. My external site is on local IIS and has the cordova.js as well as few plugins. Now just have to see if I get Apple to approve my app!
If you include the PhoneGap source as a subproject (I used 1.7 and the directions still worked, see my note at the end), you can add a few lines of code to allow PhoneGap to support external URLs as the startPage.
Around line 133, you'll want to add
if([self.startPage hasPrefix:#"http"]) {
appURL = [NSURL URLWithString:self.startPage];
}
else
right before if (startFilePath == nil) {
By default, PhoneGap doesn't seem to support external startPage URLs without a javascript 'hack' mentioned above. Other than this (and that), I know no other way!
Let me know if you have more questions.
Note: as I mentioned above, the walkthrough is missing one step. I commented on the article to let the author know, but it hasn't been approved yet. Below is my comment:
A step that was missing for me was adding $(CORDOVALIB)/Classes to the Header Search Path under Build Phases (also marking it to recursively search). Other than that, great write up!
For iOS it would be:
self.viewController.wwwFolderName = #""; // #"www"
self.viewController.startPage = #"http://192.168.2.107:9000/";
The names are confusing because the startPage is also the URL.
The simplest way I did is, include following script block in an index.html file and remove other code if not required:
<script type="text/javascript">
window.location.href="http://192.168.1.135:3000/";
</script>
And include the host in the ExternalHosts map in PhoneGap.plist file, also check OpenAllWhitelistURLsInWebView is set to YES in plist file
Setting the wwwFolderName to empty string did not work for me but nil worked.
self.viewController.wwwFolderName = nil;
self.viewController.startPage = #"http://192.168.2.107:9000/";
The simplest way I did is, xxxViewController: CDVViewController<...>
-(void) viewDidLoad{
self.wwwFolderName = #"dist";
self.startPage = #"test.html";
[super viewDidLoad];
}
so,that is all.