I'm attempting to create an iOS 5 app with some very basic FTP functionality and need some guidance. It will be connecting to a device on a local network and performing read/write actions with .dat/txt files. I've done some searching for the past few days and have seen various recommendations but nothing simple enough that I can pick up and quickly modify for my personal use.
My questions are these:
Are there any tutorials/sample code that you could recommend to me?
What frameworks and classes should I be working with for basic read/write operations?
Lastly, I should mention that I have given a considerable amount of time to analyzing the SimpleFTPSample from Apple but the sample code is giving "Connection Failure" and "Stream Open Error" notices for each example, so I'm a bit wary of its usefulness.
Forgive me if this has been answered elsewhere. All of the related posts have pieces of the answer I need, but not the whole thing. Thank you in advance!
EDIT for clarity: A well-defined example or step-by-step tutorial is what I would really like. My own Google searches have turned up nothing and I am desperately in need of some guidance here.
UPDATE:
I posted this question long ago but have continued using the FTPHelper mentioned in the accepted answer. I recently brushed the dust off the old project and realized there was a minor memory leak in FTPHelper's fetch function that can be an app-killer if called repeatedly. If anybdy stumbles across this question and chooses to use FTPHelper, be sure to add the CFRelease line seen in the code below.
- (void) fetch: (NSString *) anItem
{
if (!self.uname || !self.pword) COMPLAIN_AND_BAIL(#"Please set user name and password first");
if (!self.urlString) COMPLAIN_AND_BAIL(#"Please set URL string first");
NSString *ftpRequest = [NSString stringWithFormat:#"%#/%#", self.urlString, [anItem stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
/* CFShow(ftpRequest); */
NSString *writepath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
self.filePath = [writepath stringByAppendingPathComponent:anItem];
CFURLRef writeURL = CFURLCreateFromFileSystemRepresentation (NULL, (const UInt8 *) [writepath UTF8String], [writepath length], NO);
MySimpleDownload((CFStringRef)ftpRequest, writeURL, (CFStringRef) self.uname, (CFStringRef)self.pword);
CFRelease(writeURL);//ADD THIS LINE TO FIX MEMORY LEAK
}
The SimpleFTPSample app is running perfect, probably there is an issue that you can't see. What I can recommend you (except Apple's example) is to check THIS example which contains a helper class for all basic FTP operations. One thing to be aware of is iOS 5 ARC. Both Apple's example and the one I linked are for older iOS versions.
There are basically 2 ways to use them in iOS 5 - by telling the compiler to not use ARC by adding -fno-objc-arc flag in [Your project] -> TARGETS -> [Your app] -> Build Phases -> Compile Sources -> [Your file], or by using the built-in tool in Xcode for converting to ARC.
I personally have tested only the first method and it works for me.
If this does not help you I can write an example, but unfortunately today I am very busy.
UPDATED:
The basic mechanism is to use [FTPHelper list:THE_FTP_URL] to list the content of a folder, then create one list with the content and depending on the type (file or folder) download using [FTPHelper download: THE_FTP_URL_WITH_THE_FILENAME_FROM_LISTING]. From here you have to implement
- (void) downloadFinished
{
//do the reading depending on the file type
NSData *data = [NSData dataWithContentsOfFile:[FTPHelper sharedInstance].filePath];
}
The uploading is achieved in a similar way - using [FTPHelper upload:FILE_TO_UPLOAD] with a file from the filesystem.
There are many libraries which you could use and they are working great. :)
For example:
http://www.chilkatsoft.com/ftp-objc.asp
http://code.google.com/p/ios-ftp-server/
I recommend using them, because coding one by yourself would take a lot of time :)
One thing to remember, as o15a3d4l11s2 said, is to be aware of ARC. If you use it don't forget to add build flags to libraries which aren't ARC.
Related
My goal is to use libphonenumber, google's phone number handling library for an iPhone project I'm working on.
After downloading it (and many many hours), I complied the C++ version of the library, and it built a number ".a" files and ".dylib" files, of which I assumed I must import into my xCodeProject in order to access those C++ functions.
So I imported "libphonenumber.a" into my project, updated my target, build settings, build phases, and Library Search Paths as needed.
Building the xCode project for Device & Simulator pass, however give me the following warning:
"ld: warning: ignoring file ../XcodeProjects/libphonenumber/build/libphonenumber.dylib, file was built for unsupported file format which is not the architecture being linked (armv7)". (or i386 when compiling for simulator)
I understand from this that I must compile the libphonenumber for the correct i386 and/or armv7 architecture. So I tried to do that, but quickly realized this requires me to also rebuild libphonenumber's 3 dependent libraries as well, for the i386/armv7 architectures in order for libphonenumber's to now properly compile. Eventually, I gave up on that, it started to look like a big mess ahead of me.
After all my trials, I'm left with
3 Questions:
1) How to I compile libphonenumber C++ library for use with i386/armv6/armv7 architectures.
2) When using a c++ library, is my assumption correct? Is it a matter of simply importing the ".a" file that results from the compilation, and just point to it in the header of my xCode project files? What exactly are the steps for including and using c++ libraries and accessing their functions from objective-c inside xCode?
3) I did find LPNKit, an objective-c port for libphonenumber, however it is incomplete. Has anyone heard of it, and had any luck using it? Or does anyone have an objective-c port for libphonenumber that is complete, working, with instructions on how to compile and install it correctly?
Any help or advice on how to get this library working on iOS would be greatly appreciated.
Update:
I ended up using the javascript version of libphonenumber, adding all the files to my bundle, including all referenced javascript libraries and using UIWebview and stringByEvaluatingJavaScriptFromString to run functions. You could also have the UIWebview reference the javascript library online (I just preferred to have everything local as not to depend on an internet connection).
Here is a sample of what I did:
webView_ = [[UIWebView alloc] init];
[webView_ loadHTMLString:
#"<script src='base.js'></script>"
"<script>"
"goog.require('goog.dom');"
"goog.require('goog.json');"
"goog.require('goog.proto2.ObjectSerializer');"
"goog.require('goog.string.StringBuffer');"
"</script>"
"<script src=\"phonemetadata.pb.js\"></script>"
"<script src=\"phonenumber.pb.js\"></script>"
"<script src=\"metadata.js\"></script>"
"<script src=\"phonenumberutil.js\"></script>"
"<script src=\"asyoutypeformatter.js\"></script>"
"<script src=\"normalize.js\"></script>"
baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] resourcePath]]];
NSString *function = [[NSString alloc] initWithFormat: #"phoneNumberParser('%#','%#','')", phoneNumber, ISOCountryCode];
NSLog(#"function is: %#", function);
NSString *result =[webView_ stringByEvaluatingJavaScriptFromString:function];
The result variable gets me the formatted number.
I hope that helps anyone who ran into the same issue I did.
It has been ported by our team.
You can find it https://github.com/me2day/libPhoneNumber-iOS
Just note that libphonenumber Javascript library includes Google's closure library.
So you should consider, wrapping your Javascript call in a Javascript object and then compile it using closure builder in order to get an efficient and light weight script. (closure library before compilation : 18Mb, after compilation 300Kb !)
See above a sample of such a wrapper
goog.provide('sphone.phonenumber');
goog.require('goog.dom');
goog.require('goog.json');
goog.require('goog.proto2.ObjectSerializer');
goog.require('goog.array');
goog.require('goog.proto2.PbLiteSerializer');
goog.require('goog.string');
goog.require('goog.proto2.Message');
goog.require('goog.string.StringBuffer');
goog.require('i18n.phonenumbers.NumberFormat');
goog.require('i18n.phonenumbers.PhoneNumber');
goog.require('i18n.phonenumbers.PhoneNumberUtil');
sphone.phonenumber = function(phoneNumber, regionCode) {
this.getCountryCallCode=phonenumberGetCountryCallCode;
};
function phonenumberGetCountryCallCode(phoneNumber, regionCode) {
var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
var number = phoneUtil.parseAndKeepRawInput(phoneNumber, regionCode);
return number.getCountryCode();
};
// Ensures the symbol will be visible after compiler renaming.
goog.exportSymbol('sphone.phonenumber', sphone.phonenumber);
1) Fix all the errors and re-compile all the dependencies for arm. As you said before.
2) Yes. According to kstenerud’s iOS-Universal-Framework
Using an iOS Framework
iOS frameworks are basically the same as regular dynamic Mac OS X frameworks, except they are statically linked.
To add a framework to your project, simply drag it into your project. When including headers from your framework, remember to use angle bracket syntax rather than quotes.
For example, with framework "MyFramework":
#import <MyFramework/MyClass.h>
This question Importing an external library in xcode - C++ follows like this: Import C++ library, use it, get errors from its dependency on built-in frameworks, import those built-in frameworks, everything works.
3) I would invest in LPNKit instead of fighting your way through option 1. You can both contribute and benefit from LPNKit. GitHub is a wonderful place and the great boost of this over option 1 is that you have another person (or people!) who have the same goal and will all work together to achieve it.
I'm considering using YAML as part of my next iPhone application, but I haven't been able to find an Objective-C library to use.
The Wikipedia page for YAML mentions one, but the link is dead.
Is there an Objective-C library that can parse YAML into native collection objects (NSArray, NSDictionary, etc...)?
The Cocoa extensions for Syck are probably what you're looking for -- it's where the library that Shaggy Frog mentioned seems to be living these days.
You can try YAML.framework it's LibYAML based, it's fast and easy to use. Follows the same pattern as standard NSPropertyListSerialization.
You can use it for iOS (iPhone/iPad) development.
The YAMLKit framework is a thin wrapper around LibYAML. It does exactly what you want. For example:
[[YKParser alloc] init];
[p readString:#"- foo\n- bar\n- baz"];
id result = [p parse];
/* result is now an NSArray containing an NSArray with elements:
#"foo", #"bar", #"baz" */
[p release];
I recently wrote modern ObjC-YAML bindings, based on the standard NSCoder/NSKeyedArchiver interface: http://github.com/th-in-gs/YACYAML. I'm using them in my own projects, and intend to maintain them for at least as long as I continue to do so.
More here: http://www.blog.montgomerie.net/yacyaml
IF you are doing alot of c++ in your iPhone projects, then please have a look at yaml-cpp:
http://code.google.com/p/yaml-cpp/
has native iPhone support (via it's cmake build system)
has no dependencies beyond a good compiler and cmake
is very c++ friendly (thus, the name) with solid documentation (see the wiki/HowToParseADocument page)
I found this right from YAML's front page. But it looks like it might be out of date (c. 2004?), and the CVS link doesn't work for me.
I would bet that it's just a thin wrapper around an underlying C library like this or this... C code being "native" code that the Objective-C compiler will grok.
I found this question looking for YAML + objective C options. I ended up using this solution: https://github.com/icanzilb/JSONModel. Very cool, up to date and easy to use. Parses yaml directly into objective C models that you create inheriting the JSONModel class.
For a personal project of mine, I'm trying to retrieve iPhone WiFi signal strength. I'm fully aware that this in the land of undocumented goodness, so please refrain from the "No Appstore" answers. :)
Anywho, I've been reading up on previous WiFi Network Scanner Apps (WiFi Stumbler), but I'm afraid most (if not all) reflect outdated SDK documentation. Hopefully, this question will also provide some centralized / insightful material with the most recent iPhone SDK 3.1.2.
Here's my incomplete/not-working code:
.h
void *libHandle;
void *airportHandle;
int (*open)(void *);
int (*bind)(void *, NSString *);
int (*close)(void *);
int (*scan)(void *, NSArray **, void *);
.m
libHandle = dlopen("/System/Library/PrivateFrameworks/MobileWiFi.framework/MobileWiFi",RTLD_LAZY);
open = dlsym(libHandle, "Apple80211Open");
bind = dlsym(libHandle, "Apple80211BindToInterface");
close = dlsym(libHandle, "Apple80211Close");
scan = dlsym(libHandle, "Apple80211Scan");
open(&airportHandle);
bind(airportHandle, #"en0");
NSLog(#"Result %#",libHandle);
When executed on the device, it'll produce my ever-so-favorite...
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
I'm thinking the dynamic loading call, isn't loading anything. The directory: /System/Library/PrivateFrameworks/ only lists a Info.plist file with no binaries or aliases.
Probably doing something terribly wrong (wrong directory?)... appreciate any help!
Also, as a follow up. To extract the WiFi information, it might be done by:
GetInfoCopy = dlsym(libHandle, "Apple80211GetInfoCopy");
And my questions are 1) Has anybody had any luck with this? 2) How do you get a header dump like I would using with class-dump on Objective-C libraries (because MobileWifi is in C)?
For anybody who stumbles upon this question, here's my library to access 802.11 networks. Although Apple claims to deny any applications that use private frameworks, there are several closed-sourced WiFi applications on the AppStore. Use at your own risk.
This library works with iPhone SDK 3.1.2.
SOLStumbler.h
SOLStumbler.m
Use:
SOLStumbler *networksManager = [[SOLStumbler alloc] init];
[networksManager scanNetworks];
Result:
An networks NSDictionary of a info NSDictionary.
Use CFShow to explore the returned pointer containing information. Or call the description method for sample output.
Update as of July 2012 (iOS 5.0)
The code you're trying to use is pretty old. This stuff (e.g. WiFiManager or MobileWiFi) is in a private framework. That means Apple can, and often will, change it or move if from OS version to version.
I ran nm on the MobileWifi framework, and didn't see any of those function names. So, I think that's why your code fails.
$ pwd
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/PrivateFrameworks/MobileWiFi.framework
$ nm MobileWiFi | grep 80211
$
I suppose it might be necessary to run nm on the actual device framework, but I didn't waste my time, after looking at this:
Discussion of this framework, and follow-ons.
It looks like you can now find equivalent (?) functions in the IPConfiguration framework. Try this code:
libHandle = dlopen("/System/Library/SystemConfiguration/IPConfiguration.bundle/IPConfiguration", RTLD_LAZY);
I ran it on a jailbroken iOS 5.0.1 phone and it worked (loaded the dylib and found a few of the Apple80211 functions). From that thread I linked to, it looks like you may need to have this installed in /Applications on a jailbroken phone, in order to work fully. Or, possibly have to mess around with adding some entitlements to your sandboxed app.
These Apple80211xxx functions do not exist in MobileWiFi.framework (you can check using the `nm' tool against the SDK binaries).
(Also, it's impossible to dump a C header from binaries because all type information are removed during compilation. You need to reverse engineer it yourself or wait for someone to do so.)
I'm not sure if this would be a problem, but open/close/bind are names that are already in-use (standard C library).
The binary doesn't exist, as it is stored in the dyld shared_cache (dlopen will succeed because the library is technically 'loaded.'); however, I note that you're not checking that any of libHandle, open, close, bind or scan are valid when you retrieve them from the dl* functions.
I need to write some code that will let me query a m4a file and extract the chapter information out. Including:
chapter name
chapter start time
chapter artwork
I did some quick searching and it seems this is viewed as proprietary information by Apple? I found some discussions, but most were from 2005. Also there have been some similar questions on here, but more for CREATING m4a files with chapters, not querying.
Is this just something I have to DIY, cause there isn't a nice apple API for me to use? Or am I missing something obvious?
Also, ideally I need whatever technique I end up using to work on the iPhone.
The metadata tags system is Apple-proprietary. To work with the tags, you have to (sigh) reverse-engineer it or work with a library that has already done this.
I found the following links, but honestly it seems like you will have to pull out the hex editor.
Binary format info (basic spec for generic tags)
Perl library for working with M4A files.
Turns out this is much simpler than talked about here in the "answers". Not sure if this works on the iPhone, but I just tested it in a command line app:
QTMovie* movie = [QTMovie movieWithFile:#"filename.m4a" error:nil];
NSInteger numChapters = [movie chapterCount];
NSLog(#"Number of Chapters: %d", numChapters);
NSArray* chapterArray = [movie chapters];
for ( NSDictionary* chapDict in chapterArray )
{
NSLog(#"%#", [chapDict objectForKey:#"QTMovieChapterName"] );
}
Easy as pie. DOH!
this library should solve your needs, but is not runnable on iphone without jailbreaking I would think. http://wmptagext.sourceforge.net/
oops if you need it to work on iphone there is probably an apple api to get this info. /me looks
it sounds like you need to play around with the ipodlibrary library....
http://developer.apple.com/iphone/library/documentation/Audio/Conceptual/iPodLibraryAccess_Guide/UsingTheiPodLibrary/UsingTheiPodLibrary.html#//apple_ref/doc/uid/TP40008765-CH101-SW1
If the files in question live in the iPod library,
maybe you can get your information via the MPMediaLibrary
query interface (3.0 upward).
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Can anyone recommend a C or Objective-C library for HTML parsing? It needs to handle messy HTML code that won't quite validate.
Does such a library exist, or am I better off just trying to use regular expressions?
I found using hpple quite useful to parse messy HTML. Hpple project is a Objective-C wrapper on the XPathQuery library for parsing HTML. Using it you can send an XPath query and receive the result .
Requirements:
-Add libxml2 includes to your project
Menu Project->Edit Project Settings
Search for setting "Header Search Paths"
Add a new search path "${SDKROOT}/usr/include/libxml2"
Enable recursive option
-Add libxml2 library to to your project
Menu Project->Edit Project Settings
Search for setting "Other Linker Flags"
Add a new search flag "-lxml2"
-From hpple get the following source code files an add them to your project:
TFpple.h
TFpple.m
TFppleElement.h
TFppleElement.m
XPathQuery.h
XPathQuery.m
-Take a walk on w3school XPath Tutorial to feel comfortable with the XPath language.
Code Example
#import "TFHpple.h"
NSData *data = [[NSData alloc] initWithContentsOfFile:#"example.html"];
// Create parser
xpathParser = [[TFHpple alloc] initWithHTMLData:data];
//Get all the cells of the 2nd row of the 3rd table
NSArray *elements = [xpathParser searchWithXPathQuery:#"//table[3]/tr[2]/td"];
// Access the first cell
TFHppleElement *element = [elements objectAtIndex:0];
// Get the text within the cell tag
NSString *content = [element content];
[xpathParser release];
[data release];
Known issues
As hpple is a wrapper over XPathQuery which is another wrapper, this option probably is not the most efficient. If performance is an issue in your project, I recommend to code your own lightweight solution based on hpple and xpathquery library code.
Looks like libxml2.2 comes in the SDK, and libxml/HTMLparser.h claims the following:
This module implements an HTML 4.0 non-verifying parser with API compatible with the XML parser ones. It should be able to parse "real world" HTML, even if severely broken from a specification point of view.
That sounds like what I need, so I'm probably going to use that.
Just in case anyone has got here by googling for a nice XPath parser and gone off and used TFHpple, Note that TFHpple uses XPathQuery. This is pretty good, but has a memory leak.
In the function *PerformXPathQuery, if the nodes are found to be nil, it jumps out before cleaning up.
So where you see this bit of code: Add in the two cleanup lines.
xmlNodeSetPtr nodes = xpathObj->nodesetval;
if (!nodes)
{
NSLog(#"Nodes was nil.");
/* Cleanup */
xmlXPathFreeObject(xpathObj);
xmlXPathFreeContext(xpathCtx);
return nil;
}
If you are doing a LOT of parsing, it's a vicious leak.
Now.... how do I get my night back :-)
I wrote a lightweight wrapper around libxml which maybe useful:
Objective-C-HMTL-Parser
This probably depends on how messy the HTML is and what you want to extract. But usually Tidy does quite a good job. It is written in C and I guess you should be able to build and statically link it for the iPhone. You can easily install the command line version and test the results first.
You may want to check out ElementParser. It provides "just enough" parsing of HTML and XML. Nice interfaces make walking around XML / HTML documents very straightforward. http://touchtank.wordpress.com/
How about using the Webkit component, and possibly third party packages such as jquery for tasks such as these? Wouldn't it be possible to fetch the html data in an invisible component and take advantage of the very mature selectors of the javascript frameworks?
Google's GData Objective-C API reimplements NSXMLElement and other related classes that Apple removed from the iPhone SDK. You can find it here http://code.google.com/p/gdata-objectivec-client/. I've used it for dealing messaging via Jabber. Of course if your HTML is malformed (missing closing tags) this might not help much.
We use Convertigo to parse HTML on the server side and return a clean and neat JSON web services to our Mobile Apps