I need to save unsigned char array to NSPasteBoard and then read it. How I can do it? I tried to save it to NSString, but this working only with ASCII codes.
Try this:
char myChars[] = "This is a test";
NSData *charsData = [NSData dataWithBytes:myChars length:strlen(myChars)];
[[NSPasteboard generalPasteboard] clearContents];
[[NSPasteboard generalPasteboard] setData:charsData forType:NSPasteboardTypeString];
NSData *data = [[NSPasteboard generalPasteboard] dataForType:NSPasteboardTypeString];
char myChars2[data.length];
[data getBytes:myChars2 length:data.length];
NSLog(#"%s", myChars2);
The question is a bit unclear. Do your application use pasteboard to communicate with other apps or just to store data between launches?
1. Your application needs to store binary data for itself between launches.
I suggest you to use NSUserDefaults for that purpose. As it said in docs, it's a database so you may achieve data even in next application launch.
static const NSString *kCharsDefaultsKey = #"kCharsDefaultsKey";
- (void)saveChars:(unsigned char *)chars length:(size_t)length
{
NSData *data = [NSData dataWithBytes:chars length:length];
NSUserDefaults *defaults = [NSUserDefaults standartDefaults];
[defaults setValue:data forKey:kCharsDefaultsKey];
[defaults synchronize];
}
- (void)getChars:(unsigned char *)chars length:(size_t)length
{
NSUserDefaults *defaults = [NSUserDefaults standartDefaults];
NSData *data = [default valueForKey:kCharsDefaultsKey];
if(data)
{
[data getBytes:chars];
}
}
2. Your application needs to push data between some apps.
The pasteboard-mechanism can be a way to establish this kind of communication. But I strongly recommend you to choose another way. You can't be sure there isn't another data inside the pasteboard.
- (void)someMethod
{
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSArray *contents = [pasteboard readObjectsForClasses:#[[NSData class]] options: nil];
// how should you distinguish which object contains your chars and which doesn't?
}
I would rather recommend you to use NSConnection.
Also please take a look at this great article.
Related
I'm trying to setup the new ios 10 push notifications that are mutable, and in the didReceiveRequest method I am trying to read some argruments, one that is stored in NSUserDefaults and one that is in a local JSON file like this:
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSInteger index = [defaults integerForKey:#"index"];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Words" ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSString *word = dict[#"Irish"][index];
self.bestAttemptContent.body = [NSString stringWithFormat:#"%#", word];
self.contentHandler(self.bestAttemptContent);
}
The problem is the method runs too slowly and doesn't finish. I know this is the case because apple warns about it and because if I replace that whole method above with a simple line that changes the title to a random string then it runs fine. Does anyone know how to make this faster or a way around this ?
What I'm trying to accomplish is each day the 'index' variable will increase when a daily push notification is recieved and it should read that index from the json file. So I basically want the user to receive the next string in the JSON file each day
Thanks
Why dont you do the actual processing in a new thread and return to complete the method call:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
self.contentHandler = contentHandler;
...
});
I got some static data, not too much, maybe 50-60 counts, which is necessary for view's content, so I have to preload them into my app. The data is not plain, not appropriate for property list,and it is too small so I'm not sure if core data is fit. Any suggestion?
I think you can convert them into NSData then save into a file.
For example:
//Write
NSArray * array = #[#"1",#"2",#"3",#"4"];
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:array];
[data writeToFile:yourpath atomically:YES];
//Read
NSData * data = [NSData dataWithContentsOfFile:writeToFile:yourpath];
NSArray * array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
So i would like to make a file called "SavedData.h" "SavedData.m" and store all my games saved data in these files...
How would I wire the whole process up to run in my "MainView.h" and "MainView.m"
I'm not that experienced with xcode...
The action in the MainView.m:
- (IBAction)btncheck:(id)sender {
if ([answer isEqualToString:#"Pizza Pie"]) {
//Name:Pizza Pie *SAVED
NSString *savestring = _textbox.text;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:savestring forKey:#"savedstring"];
[defaults synchronize];
}
_textbox is my textField
and in my SavedData.m:
//Name:Pizza Pie
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *loadstring = [defaults objectForKey:#"savedstring"];
[_textbox setText:loadstring];
}
How is this done?
& is it even possible?
I think you're aiming to save state to a file and restore it later (you wouldn't use source files for this, there's no compiler on the phone). Steps are:
Put whatever you want to save in a dictionary:
NSMutableDictionary *myState = [NSMutableDictionary dictionary];
myState[#"foo"] = #"bar";
Get a path to where you're app is allowed to save:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *pathFile = [paths[0] stringByAppendingPathComponent:#"mystate.plist"];
Save:
[myState writeToFile:pathFile atomically:YES];
Read it later:
myState = [[NSDictionary alloc] initWithContentsofFile:pathFile];
You can also build a mutable dictionary this same way (replace NSDictionary in the last line with NSMutableDictionary).
I'me trying to save a variable into hard drive to load it on my app startup. I do the following:
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
votesFile = [documentsDirectory stringByAppendingPathComponent:#"votes.dat"];
Yet, this is creating no file, at least that I can see. When I try to do this:
[votes writeToFile:votesFile atomically:YES]; //votes!=nil
and then
votes = [[NSMutableDictionary alloc] initWithContentsOfFile: votesFile];
it does nothing for me, votes == nil
What am I missing here?
If you are using a NSDictionary with NSStrings as keys, and NSNumbers as values, those classes are compatible with Archiving and Unarchiving pattern, so you can use NSUserDefaults to store your data, and load it the next time you run the application.
To save your data:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:yourVotesDictionary forKey:aKey];
[defaults synchronize]; //This is very important when you finish saving all your data.
To load your data:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableDictionary *votes = [defaults objectForKey:yourNSString];
As you can see, NSUserDefaults is a dictionary, and it behaves like that.
Hope it helps,
have a good day.
There can be various errors using writeToFile:atomically: which is why it returns a BOOL. You should have something like:
if(![votes writeToFile:votesFile atomically:YES]) {
NSLog(#"An error occurred");
}
If you are getting an error there you have an issue with your NSDictionary.
The question title pretty much gives it away - I'd like my app to remember a few things. It's some sort of calculator, so it should save the last used values and some user selectable settings.
Basically I'd like to save a handful of floats and BOOLs and load them again the next time the app loads.
What's the best and easiest way to do that?
Thanks!!
One of the easiest ways would be saving it in the NSUserDefaults:
Setting:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:value
forKey:key];
// – setBool:forKey:
// – setFloat:forKey:
// in your case
[userDefaults synchronize];
Getting:
[[NSUserDefaults standardUserDefaults] objectForKey:key];
– boolForKey:
and
– floatForKey: in your case.
Besides the very good NSUserDefaults approach, there is another easy way to store data from an NSArray,NSDictionary or NSData in a file. You can use these methods as well:
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
respectively (for a NSDictionary):
+ (id)dictionaryWithContentsOfFile:(NSString *)path
you just have to give a valid path to a location. According to the iOS Application Programming Guide, the /Library/Caches directory would be the best place to store data that you need to persist between app launches. (see here)
In order to store/load a dictionary from a filed called "managers" in your document directoy you could use these methods:
-(void) loadDictionary {
//get the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSCachesDirectory, NSUserDomainMask, YES);
NSString *cacheDirectory = [paths objectAtIndex:0];
//create a destination file name to write the data :
NSString *fullFileName = [NSString stringWithFormat:#"%#/managers", cacheDirectory];
NSDictionary* panelLibraryContent = [NSDictionary dictionaryWithContentsOfFile:fullFileName];
if (panelLibraryContent != nil) {
// load was successful do something with the data...
} else {
// error while loading the file
}
}
-(void) storeDictionary:(NSDictionary*) dictionaryToStore {
//get the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cacheDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the
//cache directory:
NSString *fullFileName = [NSString stringWithFormat:#"%#/managers", cacheDirectory];
if (dictionaryToStore != nil) {
[dictionaryToStore writeToFile:fullFileName atomically:YES];
}
}
Anyway this approach is very limited and you have to spend a lot of extra work if you want to store more complex data. In that case the CoreData API is very very handy.
In Swift:
Setting
let userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setObject(value, forKey: key)
// userDefaults.setFloat(12.34, forKey: "myFloatKey")
// userDefaults.setBool(true, forKey: "myBoolKey")
Note that for iOS 8 and later, calling userDefaults.synchronize() is not recommended.
Getting
let userDefaults = NSUserDefaults.standardUserDefaults()
if let value = userDefaults.objectForKey(key) {
print(value)
}
Note that userDefaults.boolForKey and userDefaults.floatForKey both return non optional values, so they would never be nil (only false or 0.0).
Further reading
NSUserDefaults — A Swift Introduction
You are looking for NSUserDefaults
Swift 4 / Linux
Apparently something has changed. Now there's the UserDefault class.
Check these links:
https://developer.apple.com/documentation/foundation/userdefaults
https://www.hackingwithswift.com/read/12/2/reading-and-writing-basics-userdefaults