Что правильный путь состоит в том, чтобы проверить на пустую строку в Objective C?

Я давно хотел что-то подобное - многие страницы, которые мы пишем, могли бы быть сгенерированы младшим разработчиком, если бы им не нужно было писать кучу запросов; и, в любом случае, это один и тот же базовый шаблонный запрос - зачем им писать их для каждого контроллера, когда большая часть их работы состоит в том, чтобы получить контент? Я использую C #, поэтому мне не приходится иметь дело с управлением памятью. Почему HTML-кодер должен иметь дело с деталями запроса?

Существует способ, позволяющий неявно загружать данные асинхронно в View. , Сначала вы определяете класс, который выражает, какие данные вы хотите. Затем в верхней части каждого представления создайте экземпляр этого класса. Вернувшись в контроллер, вы можете найти представление, которое, как вы знаете, собираетесь использовать, открыть его, а затем скомпилировать этот класс . Затем вы можете использовать его, чтобы получить данные, необходимые представлению, асинхронно, в контроллере, как это обеспечивает MVC. Наконец, передайте его с помощью ViewModel в View, как предписывает MVC, и, через некоторую хитрость, у вас будет View, который объявляет, какие данные он собирается использовать.

Вот StoryController. Младшие разработчики пишут истории в виде простых файлов .cshtml, не зная, что такое контроллер, база данных или LINQ:

public class StoryController : BaseController
{
    [OutputCache(Duration=CacheDuration.Days1)]
    // /story/(id)
    public async Task<ActionResult> Id(string id = null)
    {
        string storyFilename = id;

        // Get the View - story file
        if (storyFilename == null || storyFilename.Contains('.'))
            return Redirect("/");   // Disallow ../ for example

        string path = App.O.AppRoot + App.HomeViews + @"story\" + storyFilename + ".cshtml";
        if (!System.IO.File.Exists(path))
            return Redirect("/");

        return View(storyFilename);

Пока все, что нужно сделать, это получить файл View на основе URL, что-то вроде Веб-формы (за исключением внутри MVC и с использованием Razor). Но мы хотим показать некоторые данные - в нашем случае, людей и проекты, которые накапливаются в базе данных - с некоторыми стандартными ViewModels и Partials. Давайте определимся как и скомпилируем это. (Обратите внимание, что в моем случае ConservX является основным пространством имен Project).

    public async Task<ActionResult> Id(string id = null)
    {
        string storyFilename = id;

        // 1) Get the View - story file
        if (storyFilename == null || storyFilename.Contains('.'))
            return Redirect("/");   // Disallow ../ for example

        string path = App.O.AppRoot + App.HomeViews + @"story\" + storyFilename + ".cshtml";
        if (!System.IO.File.Exists(path))
            return Redirect("/");

        // 2) It exists - begin parsing it for StoryDataIds
        var lines = await FileHelper.ReadLinesUntilAsync(path, line => line.Contains("@section"));

        // 3) Is there a line that says "new StoryDataIds"?
        int i = 0;
        int l = lines.Count;
        for (; i < l && !lines[i].Contains("var dataIds = new StoryDataIds"); i++)
        {}

        if (i == l) // No StoryDataIds defined, just pass an empty StoryViewModel
            return View(storyFilename, new StoryViewModel());


        // https://stackoverflow.com/questions/1361965/compile-simple-string
        // https://msdn.microsoft.com/en-us/library/system.codedom.codecompileunit.aspx
        // https://msdn.microsoft.com/en-us/library/system.codedom.compiler.codedomprovider(v=vs.110).aspx
        string className = "__StoryData_" + storyFilename;
        string code = String.Join(" ",
            (new[] {
                "using ConservX.Areas.Home.ViewModels.Storying;",
                "public class " + className + " { public static StoryDataIds Get() {"
            }).Concat(
                lines.Skip(i).TakeWhile(line => !line.Contains("};"))
            ).Concat(
                new[] { "}; return dataIds; } }" }
            ));


        var refs = AppDomain.CurrentDomain.GetAssemblies();
        var refFiles = refs.Where(a => !a.IsDynamic).Select(a => a.Location).ToArray();
        var cSharp = (new Microsoft.CSharp.CSharpCodeProvider()).CreateCompiler();
        var compileParams = new System.CodeDom.Compiler.CompilerParameters(refFiles);
        compileParams.GenerateInMemory = true;
        compileParams.GenerateExecutable = false;

        var compilerResult = cSharp.CompileAssemblyFromSource(compileParams, code);
        var asm = compilerResult.CompiledAssembly;
        var tempType = asm.GetType(className);
        var ids = (StoryDataIds)tempType.GetMethod("Get").Invoke(null, null);

        using (var db... // Fetch the relevant data here

        var vm = new StoryViewModel();
        return View(storyFilename, vm);
    }

Это большая часть работы. Теперь младшие разработчики могут просто объявить необходимые данные следующим образом:

@using ConservX.Areas.Home.ViewModels.Storying
@model StoryViewModel
@{
    var dataIds = new StoryDataIds
    {
        ProjectIds = new[] { 4 }
    };

    string title = "Story Title";
    ViewBag.Title = title;
    Layout = "~/Areas/Home/Views/Shared/_Main.cshtml";
}
@section css {
...
179
задан Ashwini Shahapurkar 24 February 2014 в 20:18
поделиться

5 ответов

As others have pointed out, there are many kinds of "null" under Cocoa/Objective C. But one further thing to note is that [title isKindOfClass:[NSNull class]] is pointlessly complex since [NSNull null] is documented to be a singleton so you can just check for pointer equality. See Topics for Cocoa: Using Null.

So a good test might be:

if (title == (id)[NSNull null] || title.length == 0 ) title = @"Something";

Note how you can use the fact that even if title is nil, title.length will return 0/nil/false, ie 0 in this case, so you do not have to special case it. This is something that people who are new to Objective C have trouble getting used to, especially coming form other languages where messages/method calls to nil crash.

390
ответ дан 23 November 2019 в 06:15
поделиться

Если такого рода вещи еще не существуют, вы можете создать категорию NSString:

@interface NSString (TrucBiduleChoseAdditions)

- (BOOL)isEmpty;

@end

@implementation NSString (TrucBiduleChoseAdditions)

- (BOOL)isEmpty {
    return self == nil || [@"" isEqualToString:self];
}

@end
0
ответ дан 23 November 2019 в 06:15
поделиться

Если вы хотите протестировать все пустые / пустые объекты (например, пустые строки или пустые массивы / наборы), вы можете использовать следующее:

static inline BOOL IsEmpty(id object) {
    return object == nil
        || ([object respondsToSelector:@selector(length)]
        && [(NSData *) object length] == 0)
        || ([object respondsToSelector:@selector(count)]
        && [(NSArray *) object count] == 0);
}
4
ответ дан 23 November 2019 в 06:15
поделиться

См. Следующие статьи на этом сайте:

Я думаю, ваша ошибка связана с чем-то другим, так как вам не нужно выполнять дополнительную проверку.

Также см. этот связанный вопрос: Правильная проверка пустого текстового столбца sqlite

6
ответ дан 23 November 2019 в 06:15
поделиться

это так же просто, как

if([object length] >0)
{
  // do something
}

помните, что в объекте C, если объект равен нулю, он возвращает 0 в качестве значения.

Это даст вам как пустую строку, так и длину 0 строка.

25
ответ дан 23 November 2019 в 06:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: