What does it mean by references? - objective-c

I'm taking a tutorial for X-code that says this:
"Go into the code and change the references from DrinkArray to DrinksDirections."
What exactly does it mean?
I would show you the tutorial, except it's a book that costs money.
The only reference I found of DrinkArray is:
- (void)viewDidLoad {
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"DrinkArray" ofType:#"plist"];
NSMutableArray* tmpArray = [[NSMutableArray alloc] initWithContentsOfFile:path];
self.drinks = tmpArray;
[tmpArray release];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

"Reference" is not a precise technical term in Objective-C, so what it means is whatever the author meant was thinking of when he wrote it. The term is sometimes used in "passed by reference" or "returned by reference," in which case "reference" means "pointer" — but that doesn't seem to be the usage here. Most likely the tutorial means to change places where your code mentions "DrinkArray" to instead say "DrinksDirections."

This is from Head First iPhone Development. The code in viewDidLoad that you found is where you want to make the change:
NSString *path = [[NSBundle mainBundle] pathForResource:#"DrinkArray"
ofType:#"plist"];
This line basically asks for the file path to the DrinkArray.plist bundled with the application. In the tutorial the next step is to migrate to a dictionary based array where each element contains a name, ingredients and directions.
Rather than typing out each entry by hand, they've provided a copy of the updated plist named DrinkDirections.plist in the book downloads. After downloading the sample files, copy the DrinkDirections.plist into your project Resources folder. Then change the line in viewDidLoad to
NSString *path = [[NSBundle mainBundle] pathForResource:#"DrinkDirections"
ofType:#"plist"];
This asks for the path to the DrinkDirections.plist that you've just added to your project. Be aware that your application will crash after making this change - that's OK, it's part of the tutorial and is covered in the immediately following pages.

okay, I figured it out. It wasn't DrinkDirections, it was DrinksDirections. It's stupid that a little thing can mess up a whole program.

The type of some declared reference variable is DrinkArray. It's telling you to change the type to DrinksDirection. Can you paste the code snippet?

Related

How to use Fragaria Framework in Objective-C?

I am trying to get Fragaria to color / Sytax highlight my Scring, but it doesnt work,
I create a blank new Project
Add the Fragaria Framework (it works)
add a custom View in Interface Builder and set its Class to MGSFragariaView
I create an Outlet, call it editor.
i also add this line because i saw it in other Samples:
#class MGSFragariaView;
Now i try to config the editor like this:
_editor.syntaxDefinitionName = #"Shell";
NSString *source = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"sh"];
NSString *code = [NSString stringWithContentsOfFile:source encoding:NSUTF8StringEncoding error:nil];
_editor.string = code;
[_editor setSyntaxColoured:YES];
But no matter what i try, the Code does not highlight, it remains simply black with no errrors or warning, why?
What am i missing?
Nevermind, Fragaria worked as expected, i was using a fork from Microsoft, it seems there were some issues with Dark Mode on MacOS coloring the ttext

Drag Files come across Sandbox(__CFPasteboardIssueSandboxExtensionForPath)

I processed drag operation from browser view to custom view.It work well in snow lepoard,but not in Mountain Lion with sandbox.
in browser view:
NSMutableArray* urls = [[[NSMutableArray alloc] init] autorelease];
..............put some NSUrl to urls array....................
[pasteboard writeObjects:[NSArray arrayWithArray:urls]];
in my receive custom view:
NSArray* pasteboardItems = [pasteboard readObjectsForClasses:[NSArray arrayWithObject:[NSString class]] options:nil];
NSArray* pasteboardItems2 = [pasteboard readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:nil];
NSArray* pasteboardItems3 = [pasteboard readObjectsForClasses:[NSArray arrayWithObject:[NSImage class]] options:nil];
NSLog(#"%#",pasteboardItems);
NSLog(#"%#",pasteboardItems2);
NSLog(#"%#",pasteboardItems3);
my log is:
2012-08-09 18:33:43.886 iCollage[6885:303] __CFPasteboardIssueSandboxExtensionForPath: error for [/Users/xxxx/Library/Containers/xxxxxxxxxxxx/Data/Downloads/1343902069.jpg]
2012-08-09 18:33:44.546 iCollage[6885:303] ( "file://localhost/Users/xxx/Library/Containers/xxxxxxxx/Data/Downloads/1343902069.jpg")
2012-08-09 18:33:44.547 iCollage[6885:303] ( "file://localhost/Users/xxxxx/Library/Containers/xxxxxx/Data/Downloads/1343902069.jpg")
2012-08-09 18:33:44.547 iCollage[6885:303] ()
my question is:
1.how to fix this error __CFPasteboardIssueSandboxExtensionForPath;I refer the docs and found nothing about that.I am ensuer that i have the permission to access the file!google says, may be "startAccessingSecurityScopedResource" will help me, then i try and failed
2.why pasteboardItems2 have value?i write to pasteboard only url but not string.It disgusted me that I can get the url both from NSString type and NSUrl type! (I try drag a file from iFinder, the url will only exist in pasteboardItems but not pasteboardItems2).Anybody know why? I think the first problem will auto fixed when some one help me fix this problem.
I believe Apple answer question 1:
Important: Although you can support dragging file paths, in general,
you should avoid doing so unless you are certain that the destination
app will never be run in an app sandbox. If you use an NSString, OS X
has no way to know whether that string should be interpreted as a
path; thus, OS X does not expand the destination app’s sandbox to
allow access to the file or directory at that location. Instead, use
an NSURL, a bookmark, or a filename pasteboard type.
WRT to question 2, it looks like you have pasted URLs so reading NSURL objects would seem to be correct. However I think you should implement the dragging using the following code (also from the link above):
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
NSPasteboard *pboard = [sender draggingPasteboard];
if ( [[pboard types] containsObject:NSFilenamesPboardType] ) {
NSArray *files = [pboard propertyListForType:NSFilenamesPboardType];
int numberOfFiles = [files count];
// Perform operation using the list of files
}
return YES;
}
You need to generate security-scoped URL bookmark data on the sender side, and turn that data back into a URL on the receiver side. There's some other stuff you have to do after that when you want to actually access the URL; the documentation elaborates.
The receiving application, when running in a sandbox, will not be able to handle bare paths. This is a core part of being sandboxed; you are not allowed to use bare paths or their corresponding URLs to access files that aren't in your sandbox container and haven't been explicitly handed to you by the user.
Your pasteboardItems read object of NSString type, but you dragged a file(with jpg extension), you should register for NSString type in your init method:
[self registerForDraggedTypes:[NSArray arrayWithObject:NSPasteboardTypeString]];
You need to have Document Types defined in your application so that the sandboxing mechanism knows your application should be opening files with those extensions. You can do this by clicking the project on the left in Xcode, and in the Info tab, under Document Types add a new document type for each extension.
You just need to fill in the name and extensions field.
Also if you want to persist your permission to access the files dragged onto your application, you can use this class to wrap up all that logic. https://github.com/leighmcculloch/AppSandboxFileAccess

NSString WriteToFile not stay permanent?

I am trying to save text stored in an NSString variable in a text file that is stored with the main bundle of my project.
So far I have had no success and tried a lot of different methods.
Why doesn't this stay permanent?
NSString *pathToFile = [[NSString alloc]init];
pathToFile = [[NSBundle mainBundle] pathForResource:#"ListOfSavedImages" ofType:#"txt"];
NSLog(#"%#",pathToFile);
NSString *stringToWriteToFile = [[NSString alloc]init];
stringToWriteToFile=#"Adam";
NSLog(#"%#",stringToWriteToFile);
[stringToWriteToFile writeToFile:pathToFile atomically:YES encoding:NSUTF8StringEncoding error:NULL];
NSLog(#"called!");
NSString *contentsOfFile1 = [NSString stringWithContentsOfFile:pathToFile encoding:NSUTF8StringEncoding error:NULL];
NSLog(#"%#",contentsOfFile1);
The actual file doesn't change although the NSLog at the end of this code segment outputs "Adam" but I am also nslogging the contents of the file when the view loads and it always reverts back to the original text(it never actually changes). What am I doing wrong?
I am using Xcode 4.3, ARC, and storyboards.
As you are instantiating your variables locally, they will leak away when you hit the end of the block }.
Try using IVars declared as properties of the particular view controller, synthesized in the .m file.
Look at the C139p at Stanford Course on ITunes, preferably the earlier series given before ARC as this fully explains the concept of data persistence.

Why isn't [NSBundle mainBundle] working here?

I've never loaded a bundle, so I'm not sure why this is not working. I don't think it matters, but the .xib in question here is in the same Resources folder as all my other .xibs.
NSArray *array = [[NSBundle mainBundle] loadNibNamed:#"S3AsyncView" owner:self];
Returns this error:
Instance method -loadNibNamed:owner not found. Return type defaults to id
I find this error strange, because the return type of [NSBundle mainBundle] is of course NSBundle.
There is no such method in NSBundle, hence the error.
I guess you are looking for:
loadNibNamed:owner:options:
Documentation link
You can pass nil to the options, as it expect a NSDictionary
So in your case:
NSArray *array = [[NSBundle mainBundle] loadNibNamed:#"S3AsyncView" owner:self options:nil];
EDIT
If it still doesn't work, verify you have included <UIKit/UIKit.h>.
EDIT 2
Ok, now I see. You tagged your question with iOS, but now you say it's a Cocoa app.
The loadNibNamed:owner:options: is a UIKit addition, so available only on iPhone.
On Mac OS X, you'll use the + (BOOL)loadNibNamed:(NSString *)aNibName owner:(id)owner class method.
So:
NSArray *array = [ NSBundle loadNibNamed: #"whatever" owner: self ];
Three things:
Make sure that you're spelling the method name right. The error message you give shows the method name as: -loadNibNamed:owner:options, which isn't right. There should be a colon after the "options". Perhaps you missed that in pasting the name into your message, but the lesson here is to check carefully that you're using exactly the right method name, with no spelling errors, omitted parts, missing colons, etc.
Make sure that you're linking against UIKit. NSBundle is part of the Foundation framework, but the -loadNibNamed:owner:options: method comes from a UIKit Additions category on NSBundle that's part of UIKit. If you don't link against UIKit, then, NSBundle won't have that method.
I see that you've removed ios from your list of tags. If you're writing for Cocoa and trying to load a nib, see the NSNib class for some convenient methods for loading nibs.
I have come across the very same problem while fixing an issue in a low-level Cocoa/Objective-C++ framework. Strictly speaking, build issue came from this function:
bool osxNibLoadMenuNibFile()
{
const auto cvAppKitVersion = floor( NSAppKitVersionNumber );
if( cvAppKitVersion >= NSAppKitVersionNumber10_8 )
{
NSBundle * mainBundle = [NSBundle mainBundle];
NSDictionary * bundleInfoDict = [mainBundle infoDictionary];
if( bundleInfoDict != nil )
{
NSString * mainNibFleNameStr = [bundleInfoDict valueForKey:#"NSMainNibFile"];
if( mainNibFleNameStr != nil )
{
if( [mainBundle loadNibNamed:mainNibFleNameStr owner:[NSApplication sharedApplication] topLevelObjects:nil] )
{
return true;
}
}
}
}
return false;
}
Clang gave me:
warning: instance method '-loadNibNamed:owner:topLevelObjects:' not found (return type defaults to 'id') [-Wobjc-method-access]
The issue was not a build configuration, as all standard frameworks were there already. The issue was more trivial: the definition of that single method is present in a separate header. So please be sure to add:
#import <AppKit/NSNibLoading.h>
which contains:
#interface NSBundle(NSNibLoading)
- (BOOL)loadNibNamed:(NSNibName)nibName owner:(nullable id)owner topLevelObjects:(NSArray * _Nullable * _Nullable)topLevelObjects API_AVAILABLE(macos(10.8));
#end
Interestingly enough, CLion gaves me "unused import directive" even though I definitely use it. Hope this helps someone!

How do I create my own store by subclassing of IASKAbstractSettingsStore?

First off, InAppSettingsKit is just what I was looking for. Once I figure out some things it will save me tons of time.
My question is: how do I create my own store by subclassing IASKAbstractSettingsStore? The home of IASK states:
The default behaviour of IASK is to store the settings in [NSUserDefaults standardUserDefaults]. However, it is possible to change this behaviour by setting the settingsStore property on an IASKAppSettingsViewController.
and
The easiest way to create your own store is to create a subclass of IASKAbstractSettingsStore.
I've spent a good deal of time combing through the code, and I think I understand the basic structure of it. However, I can't figure out how and what to set the settingsStore property to.
I can see the settingsStore defined and implemented in IASKAppSettingsViewController:
id<IASKSettingsStore> _settingsStore;
and
- (id<IASKSettingsStore>)settingsStore {
if (!_settingsStore) {
_settingsStore = [[IASKSettingsStoreUserDefaults alloc] init];
}
return _settingsStore;
}
I tried subclassing IASKAbstractSettingsStore:
#import <Foundation/Foundation.h>
#import "IASKSettingsStore.h"
#interface IASKSettingsStoreMeals : IASKAbstractSettingsStore {
NSString * _filePath;
NSMutableDictionary * _dict;
}
- (id)initWithPath:(NSString*)path;
#end
and then modified IASKAppSettingsViewController's settingsStore property to allocate and initialize my new class IASKSettingsStoreMeals instead of IASKSettingsStoreUserDefaults - the only way I can see to change the property:
- (id<IASKSettingsStore>)settingsStore {
if (!_settingsStore) {
_settingsStore = [[IASKSettingsStoreMeals alloc] init];
}
return _settingsStore;
}
When I build and run, I get the following message when I try the first control (the toggle switch), all other fields do not get saved:
attempt to insert nil value at objects[0] (key: toggleSwitch)
What am I doing wrong? In addition to the changes needed to "rejigger" the code to use IASKSettingsStoreFile (or a subclassed IASKAbstractSettingsStore), I also can't see where to set the file path change the location of where the settings are saved - or is that done behind the scenes. Looking forward to get past this learning curve and using this.
Found the answer.
My question reveals my inexperience with object orientated languages on the whole, and the concept of encapsulation and frameworks in particular. No changes needed to be made to the IASK framework code, all code was added on my root view controller.
I created another instance of IASKAppSettingsViewController, and added the following code to change the plist location:
// the path to write file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *settingsFile = [documentsDirectory stringByAppendingPathComponent:#"mySettings"];
IASKSettingsStoreFile *mySettingsBundle = [[IASKSettingsStoreFile alloc] initWithPath:settingsFile];
self.appSettingsViewController.settingsStore = mySettingsBundle;
UINavigationController *aNavController = [[UINavigationController alloc] initWithRootViewController:self.appSettingsViewController];
[mySettingsBundle release];
self.appSettingsViewController.settingsStore = mySettingsBundle;
//[viewController setShowCreditsFooter:NO]; // Uncomment to not display InAppSettingsKit credits for creators.
// But we encourage you not to uncomment. Thank you!
self.appSettingsViewController.showDoneButton = YES;
[self presentModalViewController:aNavController animated:YES];
[aNavController release];